[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog configure.ac gui/Makefile.am gu...
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ChangeLog configure.ac gui/Makefile.am gu... |
Date: |
Thu, 24 Aug 2006 00:57:21 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Sandro Santilli <strk> 06/08/24 00:57:20
Modified files:
. : ChangeLog configure.ac
gui : Makefile.am gtk.cpp gui.cpp
server : Makefile.am sprite_instance.h
server/asobj : Makefile.am
Added files:
server/asobj : MovieClip.cpp MovieClip.h
server/parser : Makefile.am action_buffer.cpp action_buffer.h
bitmap_character_def.h character_def.cpp
character_def.h edit_text_character_def.cpp
edit_text_character_def.h movie_def_impl.cpp
movie_def_impl.h movie_definition.h
shape_character_def.cpp shape_character_def.h
sprite_definition.cpp sprite_definition.h
text_character_def.h
Removed files:
server : MovieClip.cpp MovieClip.h Object.h
action_buffer.cpp action_buffer.h
bitmap_character_def.h character_def.cpp
character_def.h edit_text_character_def.cpp
edit_text_character_def.h movie_def_impl.cpp
movie_def_impl.h movie_definition.h
shape_character_def.cpp shape_character_def.h
sprite_definition.cpp sprite_definition.h
Log message:
Moved some of parser's files under their own dir/lib (not yet
finished); also moved MovieClip under asobj/, where it belongs.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.697&r2=1.698
http://cvs.savannah.gnu.org/viewcvs/gnash/configure.ac?cvsroot=gnash&r1=1.102&r2=1.103
http://cvs.savannah.gnu.org/viewcvs/gnash/gui/Makefile.am?cvsroot=gnash&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/gnash/gui/gtk.cpp?cvsroot=gnash&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/gnash/gui/gui.cpp?cvsroot=gnash&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.59&r2=1.60
http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.h?cvsroot=gnash&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/gnash/server/MovieClip.cpp?cvsroot=gnash&r1=1.3&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/MovieClip.h?cvsroot=gnash&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Object.h?cvsroot=gnash&r1=1.11&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/action_buffer.cpp?cvsroot=gnash&r1=1.18&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/action_buffer.h?cvsroot=gnash&r1=1.5&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/bitmap_character_def.h?cvsroot=gnash&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/character_def.cpp?cvsroot=gnash&r1=1.3&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/character_def.h?cvsroot=gnash&r1=1.8&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/edit_text_character_def.cpp?cvsroot=gnash&r1=1.9&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/edit_text_character_def.h?cvsroot=gnash&r1=1.8&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_def_impl.cpp?cvsroot=gnash&r1=1.35&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_def_impl.h?cvsroot=gnash&r1=1.22&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_definition.h?cvsroot=gnash&r1=1.11&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/shape_character_def.cpp?cvsroot=gnash&r1=1.7&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/shape_character_def.h?cvsroot=gnash&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_definition.cpp?cvsroot=gnash&r1=1.13&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_definition.h?cvsroot=gnash&r1=1.16&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Makefile.am?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/MovieClip.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/MovieClip.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/Makefile.am?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/action_buffer.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/action_buffer.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/bitmap_character_def.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/character_def.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/character_def.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/edit_text_character_def.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/edit_text_character_def.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/movie_def_impl.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/movie_def_impl.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/movie_definition.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/shape_character_def.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/shape_character_def.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/sprite_definition.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/sprite_definition.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/text_character_def.h?cvsroot=gnash&rev=1.1
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.697
retrieving revision 1.698
diff -u -b -r1.697 -r1.698
--- ChangeLog 24 Aug 2006 00:47:28 -0000 1.697
+++ ChangeLog 24 Aug 2006 00:57:20 -0000 1.698
@@ -1,3 +1,31 @@
+2006-08-24 Sandro Santilli <address@hidden>
+
+ * configure.ac, gui/Makefile.am, gui/gtk.cpp, gui/gui.cpp,
+ server/Makefile.am, server/MovieClip.cpp, server/MovieClip.h,
+ server/Object.h, server/action_buffer.cpp, server/action_buffer.h,
+ server/bitmap_character_def.h, server/character_def.cpp,
+ server/character_def.h, server/edit_text_character_def.cpp,
+ server/edit_text_character_def.h, server/movie_def_impl.cpp,
+ server/movie_def_impl.h, server/movie_definition.h,
+ server/shape_character_def.cpp, server/shape_character_def.h,
+ server/sprite_definition.cpp, server/sprite_definition.h,
+ server/sprite_instance.h, server/asobj/Makefile.am,
+ server/asobj/MovieClip.cpp, server/asobj/MovieClip.h,
+ server/parser/Makefile.am, server/parser/action_buffer.cpp,
+ server/parser/action_buffer.h, server/parser/bitmap_character_def.h,
+ server/parser/character_def.cpp, server/parser/character_def.h,
+ server/parser/edit_text_character_def.cpp,
+ server/parser/edit_text_character_def.h,
+ server/parser/movie_def_impl.cpp, server/parser/movie_def_impl.h,
+ server/parser/movie_definition.h,
+ server/parser/shape_character_def.cpp,
+ server/parser/shape_character_def.h,
+ server/parser/sprite_definition.cpp,
+ server/parser/sprite_definition.h,
+ server/parser/text_character_def.h:
+ Moved some of parser's files under their own dir/lib (not yet
+ finished); also moved MovieClip under asobj/, where it belongs.
+
2006-08-23 Sandro Santilli <address@hidden>
* server/swf_function.h, server/swf_function.cpp:
Index: configure.ac
===================================================================
RCS file: /sources/gnash/gnash/configure.ac,v
retrieving revision 1.102
retrieving revision 1.103
diff -u -b -r1.102 -r1.103
--- configure.ac 23 Aug 2006 20:28:20 -0000 1.102
+++ configure.ac 24 Aug 2006 00:57:20 -0000 1.103
@@ -483,6 +483,7 @@
libgeometry/Makefile
server/Makefile
server/asobj/Makefile
+server/parser/Makefile
libamf/Makefile
backend/Makefile
utilities/Makefile
Index: gui/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/gui/Makefile.am,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- gui/Makefile.am 13 Aug 2006 15:54:16 -0000 1.14
+++ gui/Makefile.am 24 Aug 2006 00:57:20 -0000 1.15
@@ -86,6 +86,7 @@
-I$(kde_includes)/kio $(all_includes) \
-I$(top_srcdir) \
-I$(top_srcdir)/server \
+ -I$(top_srcdir)/server/parser \
-I$(top_srcdir)/libbase \
-I$(top_srcdir)/backend \
-I$(top_srcdir)/libgeometry \
Index: gui/gtk.cpp
===================================================================
RCS file: /sources/gnash/gnash/gui/gtk.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- gui/gtk.cpp 11 Aug 2006 20:53:44 -0000 1.17
+++ gui/gtk.cpp 24 Aug 2006 00:57:20 -0000 1.18
@@ -40,7 +40,7 @@
#endif
#include "gnash.h"
-#include "movie_definition.h"
+//#include "movie_definition.h"
#include "log.h"
#include "gui.h"
Index: gui/gui.cpp
===================================================================
RCS file: /sources/gnash/gnash/gui/gui.cpp,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- gui/gui.cpp 10 Aug 2006 11:19:30 -0000 1.15
+++ gui/gui.cpp 24 Aug 2006 00:57:20 -0000 1.16
@@ -44,7 +44,7 @@
#include "log.h"
#include "gnash.h"
-#include "movie_definition.h"
+//#include "movie_definition.h"
#include "sprite_instance.h"
#include "gui.h"
Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -b -r1.59 -r1.60
--- server/Makefile.am 23 Aug 2006 23:03:21 -0000 1.59
+++ server/Makefile.am 24 Aug 2006 00:57:20 -0000 1.60
@@ -40,7 +40,7 @@
AM_CPPFLAGS =
-SUBDIRS = asobj
+SUBDIRS = asobj parser
# noinst_LTLIBRARIES = libserver.la
lib_LTLIBRARIES = libgnashserver.la
@@ -50,6 +50,7 @@
INCLUDES = \
-I$(top_srcdir)/server/swf \
-I$(top_srcdir)/server/asobj \
+ -I$(top_srcdir)/server/parser \
-I$(top_srcdir)/libbase \
-I$(top_srcdir) \
$(PTHREAD_CFLAGS) \
@@ -75,14 +76,12 @@
as_function.cpp \
swf_function.cpp \
character.cpp \
- character_def.cpp \
textformat.cpp \
timers.cpp \
xml.cpp \
xmlattrs.cpp \
xmlnode.cpp \
movie_root.cpp \
- movie_def_impl.cpp \
xmlsocket.cpp \
string.cpp \
action.cpp \
@@ -91,18 +90,14 @@
button.cpp \
dlist.cpp \
edit_text_character.cpp \
- edit_text_character_def.cpp \
font.cpp \
fontlib.cpp \
impl.cpp \
morph2.cpp \
- MovieClip.cpp \
render.cpp \
shape.cpp \
- shape_character_def.cpp \
shm.cpp \
sound.cpp \
- sprite_definition.cpp \
sprite_instance.cpp \
movie_instance.cpp \
stream.cpp \
@@ -133,11 +128,8 @@
button.h \
dlist.h \
character.h \
- character_def.h \
generic_character.h \
- bitmap_character_def.h \
edit_text_character.h \
- edit_text_character_def.h \
execute_tag.h \
font.h \
fontlib.h \
@@ -147,22 +139,16 @@
impl.h \
morph2.h \
morph.h \
- MovieClip.h \
movie.h \
- movie_definition.h \
- movie_def_impl.h \
movie_interface.h \
movie_root.h \
- Object.h \
resource.h \
ref_counted.h \
render.h \
shape.h \
- shape_character_def.h \
shm.h \
sound.h \
Sprite.h \
- sprite_definition.h \
sprite_instance.h \
movie_instance.h \
stream.h \
@@ -170,6 +156,7 @@
URLAccessManager.h \
styles.h \
swf.h \
+ swf_event.h \
tesselate.h \
textformat.h \
text.h \
@@ -188,9 +175,9 @@
libgnashserver_la_LIBADD = \
../libbase/libgnashbase.la \
asobj/libgnashasobjs.la \
+ parser/libgnashparser.la \
$(ZLIB_LIBS) \
$(LIBXML_LIBS) \
- $(LIBXML_LIBS) \
$(OPENGL_LIBS)
#libserver_la_LDFLAGS = -module -avoid-version -no-undefined
Index: server/sprite_instance.h
===================================================================
RCS file: /sources/gnash/gnash/server/sprite_instance.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- server/sprite_instance.h 23 Aug 2006 21:30:49 -0000 1.19
+++ server/sprite_instance.h 24 Aug 2006 00:57:20 -0000 1.20
@@ -47,7 +47,7 @@
#include <vector>
-#include "movie_definition.h"
+#include "movie_definition.h" // for inlines
#include "dlist.h" // DisplayList
#include "stream.h"
#include "log.h"
Index: server/asobj/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Makefile.am,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/asobj/Makefile.am 13 Aug 2006 15:54:16 -0000 1.4
+++ server/asobj/Makefile.am 24 Aug 2006 00:57:20 -0000 1.5
@@ -46,6 +46,7 @@
INCLUDES = \
-I$(top_srcdir)/server \
-I$(top_srcdir)/server/swf \
+ -I$(top_srcdir)/server/parser \
-I$(top_srcdir)/libbase \
-I$(top_srcdir)/libamf \
-I$(top_srcdir) \
@@ -80,6 +81,7 @@
LocalConnection.cpp\
Microphone.cpp \
Mouse.cpp \
+ MovieClip.cpp \
MovieClipLoader.cpp\
NetConnection.cpp\
NetStream.cpp \
@@ -106,6 +108,7 @@
Microphone.h \
GMath.h \
Mouse.h \
+ MovieClip.h \
MovieClipLoader.h \
NetConnection.h \
NetStream.h \
Index: server/asobj/MovieClip.cpp
===================================================================
RCS file: server/asobj/MovieClip.cpp
diff -N server/asobj/MovieClip.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/MovieClip.cpp 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,89 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include <iostream>
+#include <string>
+
+#include "MovieClip.h"
+#include "tu_file.h"
+#include "zlib_adapter.h"
+//#include "stream.h"
+//#include "jpeg.h"
+//#include "fontlib.h"
+//#include "font.h"
+#include "log.h"
+//#include "Sprite.h"
+//#include "sprite_instance.h"
+#include "render.h"
+
+using namespace std;
+
+namespace gnash
+{
+
+// Forward declarations
+
+// @@ should be found somewhere else I guess..
+//movie_interface* create_instance();
+
+void
+movieclip_init(as_object* /* global */)
+{
+#if 0
+ // This is going to be the global MovieClip "class"/"function"
+ static as_function *func=new function_as_object();
+
+ // We make the 'prototype' element be a reference to
+ // the __proto__ element
+ as_object* proto = func->m_prototype;
+ proto->add_ref();
+
+ proto->set_member("constructor", func); //as_value(func));
+ proto->set_member_flags("constructor", 1);
+
+ func->set_member("prototype", as_value(proto));
+
+ // Register _global.Function
+ global->set_member("Function", func);
+#endif
+}
+
+} // namespace gnash
+
Index: server/asobj/MovieClip.h
===================================================================
RCS file: server/asobj/MovieClip.h
diff -N server/asobj/MovieClip.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/MovieClip.h 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+
+#ifndef GNASH_MOVIECLIP_H
+#define GNASH_MOVIECLIP_H
+
+namespace gnash
+{
+
+class as_object;
+
+/// Initialize the global MovieClip constructor
+void movieclip_init(as_object* global);
+
+} // namespace gnash
+
+#endif // GNASH_MOVIECLIP_H
Index: server/parser/Makefile.am
===================================================================
RCS file: server/parser/Makefile.am
diff -N server/parser/Makefile.am
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/Makefile.am 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,97 @@
+## Process this file with automake to generate Makefile.in
+#
+# Copyright (C) 2005, 2006 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 2 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
+
+# Linking Gnash statically or dynamically with other modules is making a
+# combined work based on Gnash. Thus, the terms and conditions of the GNU
+# General Public License cover the whole combination.
+#
+# As a special exception, the copyright holders of Gnash give you
+# permission to combine Gnash with free software programs or libraries
+# that are released under the GNU LGPL and with code included in any
+# release of Talkback distributed by the Mozilla Foundation. You may
+# copy and distribute such a system following the terms of the GNU GPL
+# for all but the LGPL-covered parts and Talkback, and following the
+# LGPL for the LGPL-covered parts.
+#
+# Note that people who make modified versions of Gnash are not obligated
+# to grant this special exception for their modified versions; it is their
+# choice whether to do so. The GNU General Public License gives permission
+# to release a modified version without this exception; this exception
+# also makes it possible to release a modified version which carries
+# forward this exception.
+#
+#
+
+AUTOMAKE_OPTIONS =
+
+AM_CPPFLAGS =
+
+noinst_LTLIBRARIES = libgnashparser.la
+
+# Only enable if we're configured with --enable-mp3
+INCLUDES = \
+ -I$(top_srcdir)/server \
+ -I$(top_srcdir)/server/swf \
+ -I$(top_srcdir)/server/parser \
+ -I$(top_srcdir)/libbase \
+ -I$(top_srcdir)/libamf \
+ -I$(top_srcdir) \
+ $(PTHREAD_CFLAGS) \
+ $(ENGINE_INCLUDE) \
+ $(ZLIB_CFLAGS) \
+ $(OGG_CFLAGS) \
+ $(JPEG_CFLAGS) \
+ $(SDL_CFLAGS) \
+ $(SDL_MIXER_CFLAGS) \
+ $(OPENGL_CFLAGS) \
+ $(GTK2_CFLAGS) \
+ $(PANGO_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(CAIRO_CFLAGS) \
+ $(ATK_CFLAGS) \
+ $(DMALLOC_CFLAGS) \
+ $(LIBXML_CFLAGS)
+
+libgnashparser_la_SOURCES = \
+ action_buffer.cpp \
+ character_def.cpp \
+ edit_text_character_def.cpp \
+ movie_def_impl.cpp \
+ shape_character_def.cpp \
+ sprite_definition.cpp
+
+noinst_HEADERS = \
+ action_buffer.h \
+ character_def.h \
+ bitmap_character_def.h \
+ edit_text_character_def.h \
+ movie_definition.h \
+ movie_def_impl.h \
+ shape_character_def.h \
+ sprite_definition.h
+
+libgnashparser_la_LIBADD = \
+ ../../libbase/libgnashbase.la
+
+# Rebuild with GCC 4.x Mudflap support
+mudflap:
+ @echo "Rebuilding with GCC Mudflap support"
+ $(MAKE) CXXFLAGS="$(CXXFLAGS) -fmudflap" LDFLAGS="$(LDFLAGS) -lmudflap"
+
+clean-hook:
+ -rm -f core.*
+
Index: server/parser/action_buffer.cpp
===================================================================
RCS file: server/parser/action_buffer.cpp
diff -N server/parser/action_buffer.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/action_buffer.cpp 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,479 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "action_buffer.h"
+#include "ActionExec.h"
+#include "log.h"
+#include "stream.h"
+
+#include "swf.h"
+#include "ASHandlers.h"
+#include "as_environment.h"
+
+#include <typeinfo>
+
+#if !defined(_WIN32) && !defined(WIN32)
+# include <pthread.h>
+#endif
+
+#include <string>
+#include <stdlib.h> // for strtod
+
+using namespace gnash;
+using namespace SWF;
+using std::string;
+using std::endl;
+
+
+namespace gnash {
+
+static const SWFHandlers& ash = SWFHandlers::instance();
+
+action_buffer::action_buffer()
+ :
+ m_decl_dict_processed_at(-1)
+{
+// static int count=0;
+// printf("Action buffer %d created\n", ++count);
+}
+
+
+void
+action_buffer::read(stream* in)
+{
+ // Read action bytes.
+ for (;;) {
+#if 0
+ size_t instruction_start = m_buffer.size();
+ size_t pc = m_buffer.size();
+#endif
+
+ uint8_t action_id = in->read_u8();
+ m_buffer.push_back(action_id);
+
+ if (action_id & 0x80) {
+ // Action contains extra data. Read it.
+ uint16_t length = in->read_u16();
+ m_buffer.push_back(length & 0x0FF);
+ m_buffer.push_back((length >> 8) & 0x0FF);
+ for (uint16_t i = 0; i < length; i++) {
+ uint8_t b = in->read_u8();
+ m_buffer.push_back(b);
+ }
+ }
+
+ if (action_id == SWF::ACTION_END)
+ {
+ // end of action buffer.
+ break;
+ }
+ }
+}
+
+
+/*public*/
+void
+action_buffer::process_decl_dict(size_t start_pc, size_t stop_pc) const
+{
+ assert(stop_pc <= m_buffer.size());
+
+ if (static_cast<size_t>(m_decl_dict_processed_at) == start_pc) {
+ // We've already processed this decl_dict.
+#ifndef NDEBUG
+ int count = read_int16(start_pc+3);
+ assert((int) m_dictionary.size() == count);
+#endif
+ return;
+ }
+
+ if (m_decl_dict_processed_at != -1) {
+ log_error("process_decl_dict(%zd, %zd): decl_dict was already processed
at %d\n",
+ start_pc,
+ stop_pc,
+ m_decl_dict_processed_at);
+ return;
+ }
+
+ m_decl_dict_processed_at = start_pc;
+
+ // Actual processing.
+ size_t i = start_pc;
+ int16 length = read_int16(i+1);
+ int16 count = read_int16(i+3);
+ i += 2;
+
+//log_msg("Start at %d, stop at %d, length read was %d, count read was %d",
start_pc, stop_pc, length, count);
+
+ assert(start_pc + 3 + length == stop_pc);
+
+ m_dictionary.resize(count);
+
+ // Index the strings.
+ for (int ct = 0; ct < count; ct++) {
+ // Point into the current action buffer.
+ m_dictionary[ct] = (const char*) &m_buffer[3 + i];
+
+ while (m_buffer[3 + i]) {
+ // safety check.
+ if (i >= stop_pc) {
+ log_error("action buffer dict length exceeded\n");
+
+ // Jam something into the remaining (invalid) entries.
+ while (ct < count) {
+ m_dictionary[ct] = "<invalid>";
+ ct++;
+ }
+ return;
+ }
+ i++;
+ }
+ i++;
+ }
+}
+
+// Interpret the actions in this action buffer, and evaluate
+// them in the given environment. Execute our whole buffer,
+// without any arguments passed in.
+void
+action_buffer::execute(as_environment* env) const
+{
+ assert(env);
+
+ int local_stack_top = env->get_local_frame_top();
+ env->add_frame_barrier();
+
+ ActionExec exec(*this, *env);
+ exec();
+
+ env->set_local_frame_top(local_stack_top);
+}
+
+// Interpret the specified subset of the actions in our
+// buffer. Caller is responsible for cleaning up our local
+// stack frame (it may have passed its arguments in via the
+// local stack frame).
+//
+// The is_function2 flag determines whether to use global or local registers.
+void
+action_buffer::execute(
+ as_environment* env,
+ size_t start_pc,
+ size_t exec_bytes, // used when invoked as a function call
+ as_value* retval, // used when invoked as a function call
+ const std::vector<with_stack_entry>& initial_with_stack,
+ bool is_function2) const
+{
+ assert(env);
+ ActionExec exec(*this, *env, start_pc, exec_bytes, retval,
+ initial_with_stack, is_function2);
+ exec();
+}
+
+// Disassemble one instruction to the log.
+static void
+disasm(const unsigned char* instruction_data)
+{
+
+ as_arg_t fmt = ARG_HEX;
+ action_type action_id = (action_type)instruction_data[0];
+ unsigned char num[10];
+ memset(num, 0, 10);
+
+ dbglogfile.setStamp(false);
+ // Show instruction.
+ if (action_id > ash.lastType()) {
+ dbglogfile << "<unknown>[0x" << action_id << "]" << endl;
+ } else {
+ dbglogfile << ash[action_id].getName().c_str() << endl;
+ fmt = ash[action_id].getArgFormat();
+ }
+
+ // Show instruction argument(s).
+ if (action_id & 0x80) {
+ assert(fmt != ARG_NONE);
+ int length = instruction_data[1] | (instruction_data[2] << 8);
+ if (fmt == ARG_HEX) {
+ for (int i = 0; i < length; i++) {
+ hexify(num, (const unsigned char *)&instruction_data[3 + i], 1,
false);
+ dbglogfile << "0x" << num << " ";
+// dbglogfile << instruction_data[3 + i] << " ";
+ }
+ dbglogfile << endl;
+ } else if (fmt == ARG_STR) {
+ string str;
+ for (int i = 0; i < length; i++) {
+ str = instruction_data[3 + i];
+ }
+ dbglogfile << "\"" << str.c_str() << "\"" << endl;
+ } else if (fmt == ARG_U8) {
+ int val = instruction_data[3];
+ dbglogfile << " " << val << endl;
+ } else if (fmt == ARG_U16) {
+ int val = instruction_data[3] | (instruction_data[4] << 8);
+ dbglogfile << " " << val << endl;
+ } else if (fmt == ARG_S16) {
+ int val = instruction_data[3] | (instruction_data[4] << 8);
+ if (val & 0x8000) val |= ~0x7FFF; // sign-extend
+ dbglogfile << " " << val << endl;
+ } else if (fmt == ARG_PUSH_DATA) {
+ dbglogfile << endl;
+ int i = 0;
+ while (i < length) {
+ int type = instruction_data[3 + i];
+ i++;
+ if (type == 0) {
+ // string
+ string str;
+ while (instruction_data[3 + i]) {
+ str += instruction_data[3 + i];
+ i++;
+ }
+ i++;
+ dbglogfile << "\t\"" << str.c_str() << "\"" << endl;
+ } else if (type == 1) {
+ // float (little-endian)
+ union {
+ float f;
+ uint32_t i;
+ } u;
+ compiler_assert(sizeof(u) == sizeof(u.i));
+
+ memcpy(&u.i, instruction_data + 3 + i, 4);
+ u.i = swap_le32(u.i);
+ i += 4;
+
+ dbglogfile << "(float) " << u.f << endl;
+ } else if (type == 2) {
+ dbglogfile << "NULL" << endl;
+ } else if (type == 3) {
+ dbglogfile << "undef" << endl;
+ } else if (type == 4) {
+ // contents of register
+ int reg = instruction_data[3 + i];
+ i++;
+ dbglogfile << "reg[" << reg << "]" << endl;
+ } else if (type == 5) {
+ int bool_val = instruction_data[3 + i];
+ i++;
+ dbglogfile << "bool(" << bool_val << ")" << endl;
+ } else if (type == 6) {
+ // double
+ // wacky format: 45670123
+ union {
+ double d;
+ uint64 i;
+ struct {
+ uint32_t lo;
+ uint32_t hi;
+ } sub;
+ } u;
+ compiler_assert(sizeof(u) == sizeof(u.i));
+
+ memcpy(&u.sub.hi, instruction_data + 3 + i, 4);
+ memcpy(&u.sub.lo, instruction_data + 3 + i + 4, 4);
+ u.i = swap_le64(u.i);
+ i += 8;
+
+ dbglogfile << "(double) " << u.d << endl;
+ } else if (type == 7) {
+ // int32
+ int32_t val = instruction_data[3 + i]
+ | (instruction_data[3 + i + 1] << 8)
+ | (instruction_data[3 + i + 2] << 16)
+ | (instruction_data[3 + i + 3] << 24);
+ i += 4;
+ dbglogfile << "(int) " << val << endl;
+ } else if (type == 8) {
+ int id = instruction_data[3 + i];
+ i++;
+ dbglogfile << "dict_lookup[" << id << "]" << endl;
+ } else if (type == 9) {
+ int id = instruction_data[3 + i] | (instruction_data[3 + i
+ 1] << 8);
+ i += 2;
+ dbglogfile << "dict_lookup_lg[" << id << "]" << endl;
+ }
+ }
+ } else if (fmt == ARG_DECL_DICT) {
+ int i = 0;
+ int count = instruction_data[3 + i] | (instruction_data[3 + i + 1]
<< 8);
+ i += 2;
+
+ dbglogfile << " [" << count << "]" << endl;
+
+ // Print strings.
+ for (int ct = 0; ct < count; ct++) {
+ dbglogfile << "\t" << endl; // indent
+
+ string str;
+ while (instruction_data[3 + i]) {
+ // safety check.
+ if (i >= length) {
+ dbglogfile << "<disasm error -- length exceeded>" <<
endl;
+ break;
+ }
+ str += instruction_data[3 + i];
+ i++;
+ }
+ dbglogfile << "\"" << str.c_str() << "\"" << endl;
+ i++;
+ }
+ } else if (fmt == ARG_FUNCTION2) {
+ // Signature info for a function2 opcode.
+ int i = 0;
+ const char* function_name = (const char*) &instruction_data[3 + i];
+ i += strlen(function_name) + 1;
+
+ int arg_count = instruction_data[3 + i] | (instruction_data[3 + i +
1] << 8);
+ i += 2;
+
+ int reg_count = instruction_data[3 + i];
+ i++;
+
+ dbglogfile << "\t\tname = '" << function_name << "'"
+ << " arg_count = " << arg_count
+ << " reg_count = " << reg_count << endl;
+
+ uint16 flags = (instruction_data[3 + i]) | (instruction_data[3
+ i + 1] << 8);
+ i += 2;
+
+ // @@ What is the difference between "super" and "_parent"?
+
+ bool preload_global = (flags & 0x100) != 0;
+ bool preload_parent = (flags & 0x80) != 0;
+ bool preload_root = (flags & 0x40) != 0;
+ bool suppress_super = (flags & 0x20) != 0;
+ bool preload_super = (flags & 0x10) != 0;
+ bool suppress_args = (flags & 0x08) != 0;
+ bool preload_args = (flags & 0x04) != 0;
+ bool suppress_this = (flags & 0x02) != 0;
+ bool preload_this = (flags & 0x01) != 0;
+
+ log_msg("\t\t pg = %d\n"
+ "\t\t pp = %d\n"
+ "\t\t pr = %d\n"
+ "\t\tss = %d, ps = %d\n"
+ "\t\tsa = %d, pa = %d\n"
+ "\t\tst = %d, pt = %d\n",
+ int(preload_global),
+ int(preload_parent),
+ int(preload_root),
+ int(suppress_super),
+ int(preload_super),
+ int(suppress_args),
+ int(preload_args),
+ int(suppress_this),
+ int(preload_this));
+
+ for (int argi = 0; argi < arg_count; argi++) {
+ int arg_register = instruction_data[3 + i];
+ i++;
+ const char* arg_name = (const char*) &instruction_data[3 +
i];
+ i += strlen(arg_name) + 1;
+
+ dbglogfile << "\t\targ[" << argi << "]"
+ << " - reg[" << arg_register << "]"
+ << " - '" << arg_name << "'" << endl;
+ }
+
+ int function_length = instruction_data[3 + i] | (instruction_data[3
+ i + 1] << 8);
+ i += 2;
+
+ dbglogfile << "\t\tfunction length = " << function_length << endl;
+ }
+ } else {
+ dbglogfile << endl;
+ }
+ dbglogfile.setStamp(true);
+}
+
+// Disassemble one instruction to the log.
+void
+action_buffer::log_disasm(size_t pc) const
+{
+ const unsigned char* instruction_data =
+ (const unsigned char *)&m_buffer[pc];
+ disasm(instruction_data);
+}
+
+
+float
+action_buffer::read_float_little(size_t pc) const
+{
+ union {
+ float f;
+ uint32_t i;
+ } u;
+ compiler_assert(sizeof(u) == sizeof(u.i));
+ memcpy(&u.i, &m_buffer[pc], 4);
+ u.i = swap_le32(u.i);
+ return u.f;
+}
+
+double
+action_buffer::read_double_wacky(size_t pc) const
+{
+ // double
+ // wacky format: 45670123
+ union {
+ double d;
+ uint64 i;
+ struct {
+ uint32_t lo;
+ uint32_t hi;
+ } sub;
+ } u;
+
+ compiler_assert(sizeof(u) == sizeof(u.i));
+
+ // this works, but is pretty dirty
+ memcpy(&u.sub.hi, &m_buffer[pc], 4);
+ memcpy(&u.sub.lo, &m_buffer[pc + 4], 4);
+ u.i = swap_le64(u.i);
+
+ return u.d;
+}
+
+}
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/parser/action_buffer.h
===================================================================
RCS file: server/parser/action_buffer.h
diff -N server/parser/action_buffer.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/action_buffer.h 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,250 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+//
+
+#ifndef GNASH_ACTION_BUFFER_H
+#define GNASH_ACTION_BUFFER_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "gnash.h"
+//#include "as_object.h"
+#include "types.h"
+#include <wchar.h>
+
+#include "container.h"
+#include "smart_ptr.h"
+//#include "log.h"
+#include "with_stack_entry.h"
+
+// Forward declarations
+namespace gnash {
+ struct as_environment;
+ struct as_value;
+ namespace SWF {
+ class ActionHandler;
+ }
+}
+
+
+namespace gnash {
+
+class ActionExec;
+
+/// A code segment.
+//
+/// This currently holds the actions in a memory
+/// buffer, but I'm workin toward making this unneeded
+/// so to eventually use a gnash::stream directly and
+/// avoid full loads. (not before profiling!).
+//
+class action_buffer
+{
+
+public:
+
+ friend class ActionExec;
+
+ action_buffer();
+
+ /// Read action bytes from input stream
+ void read(stream* in);
+
+ /// \brief
+ /// Interpret the actions in this action buffer, and evaluate
+ /// them in the given environment.
+ //
+ /// Execute our whole buffer,
+ /// without any arguments passed in.
+ ///
+ /// FIXME: obsolete this, use ActionExec instead.
+ ///
+ void execute(as_environment* env) const;
+
+ /// Interpret the specified subset of the actions in our buffer.
+ //
+ /// Caller is responsible for cleaning up our local
+ /// stack frame (it may have passed its arguments in via the
+ /// local stack frame).
+ ///
+ /// FIXME: obsolete this, use ActionExec instead.
+ ///
+ void execute(
+ as_environment* env,
+ size_t start_pc,
+ size_t exec_bytes,
+ as_value* retval, // we should probably drop this parameter
+ const std::vector<with_stack_entry>& initial_with_stack,
+ bool is_function2) const;
+
+ bool is_null() const
+ {
+ return m_buffer.size() < 1 || m_buffer[0] == 0;
+ }
+
+ // kept for backward compatibility, should drop and see
+ // what breaks.
+ size_t get_length() const { return size(); }
+
+ size_t size() const { return m_buffer.size(); }
+
+ uint8_t operator[] (size_t off) const
+ {
+ assert(off < m_buffer.size() );
+ return m_buffer[off];
+ }
+
+ /// Disassemble instruction at given offset to the log.
+ void log_disasm(size_t pc) const;
+
+ /// Get a null-terminated string from given offset
+ //
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ const char* read_string(size_t pc) const
+ {
+ return (const char*)(&m_buffer[pc]);
+ }
+
+ /// Get an integer value from given offset
+ //
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ int16_t read_int16(size_t pc) const
+ {
+ int ret = m_buffer[pc] | (m_buffer[pc + 1] << 8);
+ return ret;
+ }
+
+ /// Read a 32-bit integer starting at given offset.
+ //
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ int32_t read_int32(size_t pc) const
+ {
+ int32_t val = m_buffer[pc]
+ | (m_buffer[pc + 1] << 8)
+ | (m_buffer[pc + 2] << 16)
+ | (m_buffer[pc + 3] << 24);
+ return val;
+ }
+
+ /// Read a little-endian 32-bit float starting at given offset
+ //
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ float read_float_little(size_t pc) const;
+
+ /// Read a 64-bit double starting at given offset.
+ //
+ /// wacky format: 45670123
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ double read_double_wacky(size_t pc) const;
+
+ /// Return number of entries in the constant pool
+ size_t dictionary_size() const
+ {
+ return m_dictionary.size();
+ }
+
+ /// Return a value from the constant pool
+ const char* dictionary_get(size_t n) const
+ {
+ return m_dictionary[n];
+ }
+
+ /// \brief
+ /// Interpret the SWF::ACTION_CONSTANTPOOL opcode.
+ //
+ /// Don't read stop_pc or later.
+ ///
+ /// A dictionary is some static strings embedded in the
+ /// action buffer; there should only be one dictionary per
+ /// action buffer.
+ ///
+ /// NOTE: Normally the dictionary is declared as the first
+ /// action in an action buffer, but I've seen what looks like
+ /// some form of copy protection that amounts to:
+ ///
+ /// <start of action buffer>
+ /// push true
+ /// branch_if_true label
+ /// decl_dict [0] // this is never executed, but has lots
of orphan data declared in the opcode
+ /// label: // (embedded inside the previous opcode; looks like an
invalid jump)
+ /// ... "protected" code here, including the real decl_dict
opcode ...
+ /// <end of the dummy decl_dict [0] opcode>
+ ///
+ /// So we just interpret the first decl_dict we come to, and
+ /// cache the results. If we ever hit a different decl_dict in
+ /// the same action_buffer, then we log an error and ignore it.
+ ///
+ void process_decl_dict(size_t start_pc, size_t stop_pc) const;
+
+private:
+
+ // Don't put these as values in std::vector<>! They contain
+ // internal pointers and cannot be moved or copied.
+ // If you need to keep an array of them, keep pointers
+ // to new'd instances.
+ action_buffer(const action_buffer& /*a*/) { assert(0); }
+
+ /// the code itself, as read from the SWF
+ std::vector<uint8_t> m_buffer;
+
+ /// The dictionary
+ mutable std::vector<const char*> m_dictionary;
+
+ /// FIXME: move to ActionExec
+ mutable int m_decl_dict_processed_at;
+
+};
+
+
+} // end namespace gnash
+
+
+#endif // GNASH_ACTION_BUFFER_H
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/parser/bitmap_character_def.h
===================================================================
RCS file: server/parser/bitmap_character_def.h
diff -N server/parser/bitmap_character_def.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/bitmap_character_def.h 24 Aug 2006 00:57:20 -0000
1.1
@@ -0,0 +1,114 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+//
+
+#ifndef GNASH_BITMAP_CHARACTER_DEF_H
+#define GNASH_BITMAP_CHARACTER_DEF_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gnash.h" // for bitmap_info definition
+#include "character_def.h" // for character_def inheritance
+#include "action.h"
+#include "types.h"
+#include "log.h"
+#include "container.h"
+#include "utility.h"
+#include "smart_ptr.h"
+//#include "movie_interface.h"
+#include <stdarg.h>
+
+#include <cassert>
+
+namespace gnash {
+
+/// What's this ? An interface ?
+struct bitmap_character_def : public character_def
+{
+ virtual gnash::bitmap_info* get_bitmap_info() = 0;
+};
+
+#if 1
+/// Bitmap character
+struct bitmap_character : public bitmap_character_def
+{
+ bitmap_character(bitmap_info* bi)
+ :
+ m_bitmap_info(bi)
+ {
+ }
+
+// bitmap_character(image::rgb* image)
+// {
+// assert(image != 0);
+
+// // Create our bitmap info, from our image.
+// m_bitmap_info =
gnash::render::create_bitmap_info_rgb(image);
+// }
+
+// bitmap_character(image::rgba* image)
+// {
+// assert(image != 0);
+
+// // Create our bitmap info, from our image.
+// m_bitmap_info =
gnash::render::create_bitmap_info_rgba(image);
+// }
+
+ gnash::bitmap_info* get_bitmap_info()
+ {
+ return m_bitmap_info.get_ptr();
+ }
+
+private:
+ smart_ptr<gnash::bitmap_info> m_bitmap_info;
+};
+
+#endif
+
+
+} // end namespace gnash
+
+
+#endif // GNASH_BITMAP_CHARACTER_DEF_H
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/parser/character_def.cpp
===================================================================
RCS file: server/parser/character_def.cpp
diff -N server/parser/character_def.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/character_def.cpp 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,60 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <character_def.h>
+#include <generic_character.h>
+
+namespace gnash
+{
+
+character*
+character_def::create_character_instance(character* parent, int id)
+{
+ return new generic_character(this, parent, id);
+}
+
+}
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/parser/character_def.h
===================================================================
RCS file: server/parser/character_def.h
diff -N server/parser/character_def.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/character_def.h 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,132 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+
+#ifndef GNASH_CHARACTER_DEF_H
+#define GNASH_CHARACTER_DEF_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "resource.h" // for inheritance from resource class
+
+// Forward declarations
+class tu_file;
+namespace gnash {
+ class character;
+ struct cache_options;
+ //class sprite_instance;
+}
+
+namespace gnash {
+
+/// Immutable data representing the template of a movie element.
+//
+/// This is not really a public interface. It's here so it
+/// can be mixed into movie_definition and sprite_definition,
+/// without using multiple inheritance.
+///
+struct character_def : public resource
+{
+private:
+ int m_id;
+
+public:
+ character_def()
+ :
+ m_id(-1)
+ {
+ }
+
+ virtual ~character_def() {}
+
+ virtual void display(character* /*instance_info*/)
+ {
+ }
+
+ virtual bool point_test_local(float /*x*/, float /*y*/)
+ {
+ return false;
+ }
+
+ virtual float get_height_local()
+ {
+ return 0.0f;
+ }
+
+ virtual float get_width_local()
+ {
+ return 0.0f;
+ }
+
+ /// Should stick the result in a smart_ptr immediately.
+ //
+ /// default is to make a generic_character
+ ///
+ virtual character* create_character_instance(character* parent,
+ int id);
+
+ // From resource interface.
+ virtual character_def* cast_to_character_def()
+ {
+ return this;
+ }
+
+ //
+ // Caching.
+ //
+
+ virtual void output_cached_data(tu_file* /*out*/,
+ const cache_options& /*options*/)
+ {
+ }
+
+ virtual void input_cached_data(tu_file* /*in*/)
+ {
+ }
+};
+
+
+} // namespace gnash
+
+#endif // GNASH_CHARACTER_DEF_H
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/parser/edit_text_character_def.cpp
===================================================================
RCS file: server/parser/edit_text_character_def.cpp
diff -N server/parser/edit_text_character_def.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/edit_text_character_def.cpp 24 Aug 2006 00:57:20 -0000
1.1
@@ -0,0 +1,137 @@
+// text.cpp -- Thatcher Ulrich <address@hidden> 2003
+
+// This source code has been donated to the Public Domain. Do
+// whatever you want with it.
+
+// Code for the text tags.
+
+
+#include "stream.h"
+#include "log.h"
+#include "movie_definition.h" // for m_root_def use
+
+#include "edit_text_character_def.h"
+#include "edit_text_character.h"
+
+namespace gnash {
+
+// Forward declarations
+struct movie_definition;
+
+void
+edit_text_character_def::read(stream* in, int tag_type,
+ movie_definition* m)
+{
+ assert(m != NULL);
+ assert(tag_type == SWF::DEFINEEDITTEXT); // 37
+
+ m_rect.read(in);
+
+ in->align();
+ bool has_text = in->read_uint(1) ? true : false;
+ m_word_wrap = in->read_uint(1) ? true : false;
+ m_multiline = in->read_uint(1) ? true : false;
+ m_password = in->read_uint(1) ? true : false;
+ m_readonly = in->read_uint(1) ? true : false;
+ bool has_color = in->read_uint(1) ? true : false;
+ bool has_max_length = in->read_uint(1) ? true : false;
+ bool has_font = in->read_uint(1) ? true : false;
+
+ in->read_uint(1); // reserved
+ m_auto_size = in->read_uint(1) ? true : false;
+ bool has_layout = in->read_uint(1) ? true : false;
+ m_no_select = in->read_uint(1) ? true : false;
+ m_border = in->read_uint(1) ? true : false;
+ in->read_uint(1); // reserved
+ m_html = in->read_uint(1) ? true : false;
+ m_use_outlines = in->read_uint(1) ? true : false;
+
+ if (has_font)
+ {
+ m_font_id = in->read_u16();
+ m_text_height = in->read_u16();
+ }
+
+ if (has_color)
+ {
+ m_color.read_rgba(in);
+ }
+
+ if (has_max_length)
+ {
+ m_max_length = in->read_u16();
+ }
+
+ if (has_layout)
+ {
+ m_alignment = (alignment) in->read_u8();
+ //m_left_margin = (float) in->read_u16();
+ m_left_margin = in->read_u16();
+ //m_right_margin = (float) in->read_u16();
+ m_right_margin = in->read_u16();
+ m_indent = in->read_s16();
+ m_leading = in->read_s16();
+ }
+
+ char* name = in->read_string();
+ m_default_name = name;
+ delete [] name;
+
+ if (has_text)
+ {
+ char* str = in->read_string();
+ m_default_text = str;
+ delete [] str;
+ }
+
+ IF_VERBOSE_PARSE (
+ log_parse("edit_text_char:\n"
+ " default varname = %s\n"
+ " text = ``%s''\n"
+ " font_id: %d\n"
+ " text_height: %d",
+ m_default_name.c_str(),
+ m_default_text.c_str(),
+ m_font_id,
+ m_text_height);
+ );
+}
+
+const font*
+edit_text_character_def::get_font()
+{
+ if (m_font == NULL)
+ {
+ // Resolve the font, if possible.
+ m_font = m_root_def->get_font(m_font_id);
+ if (m_font == NULL)
+ {
+ log_error("error: text style with undefined font;
font_id = %d\n", m_font_id);
+ }
+ }
+
+ return m_font;
+}
+
+character*
+edit_text_character_def::create_character_instance(character* parent,
+ int id)
+{
+ // Resolve the font, if possible
+ get_font();
+ edit_text_character* ch = new edit_text_character(parent, this, id);
+
+ ch->set_name(m_default_name.c_str());
+
+ return ch;
+}
+
+
+} // namespace gnash
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
+
Index: server/parser/edit_text_character_def.h
===================================================================
RCS file: server/parser/edit_text_character_def.h
diff -N server/parser/edit_text_character_def.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/edit_text_character_def.h 24 Aug 2006 00:57:20 -0000
1.1
@@ -0,0 +1,308 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+
+
+#ifndef _GNASH_EDIT_TEXT_CHARACTER_DEF_H_
+#define _GNASH_EDIT_TEXT_CHARACTER_DEF_H_
+
+#include "character_def.h" // for inheritance
+#include "gnash.h" // for composition (struct rect)
+#include "textformat.h" // for composition
+
+namespace gnash {
+
+// Forward declarations
+struct movie_definition;
+
+/// \brief
+/// A definition for a text display character, whose text can
+/// be changed at runtime (by script or host).
+/// This object is defined by SWF tag 37 (SWF::DEFINEEDITTEXT)
+///
+class edit_text_character_def : public character_def
+{
+
+public:
+
+ /// Text alignment values
+ enum alignment
+ {
+ ALIGN_LEFT = 0,
+ ALIGN_RIGHT,
+ ALIGN_CENTER,
+ /// probably don't need to implement...
+ ALIGN_JUSTIFY
+ };
+
+ edit_text_character_def(movie_definition* root_def)
+ :
+ m_root_def(root_def),
+ m_format(),
+ m_word_wrap(false),
+ m_multiline(false),
+ m_password(false),
+ m_readonly(false),
+ m_auto_size(false),
+ m_no_select(false),
+ m_border(false),
+ m_html(false),
+ m_use_outlines(false),
+ m_font_id(-1),
+ m_font(NULL),
+ m_text_height(1),
+ m_max_length(0),
+ m_alignment(ALIGN_LEFT),
+ m_left_margin(0),
+ m_right_margin(0),
+ m_indent(0),
+ m_leading(0)
+ {
+ assert(m_root_def);
+
+ m_color.set(0, 0, 0, 255);
+ }
+
+ /// Set the format of the text
+ void set_format(text_format &format)
+ {
+ m_format = format;
+ }
+
+ ~edit_text_character_def()
+ {
+ }
+
+ /// Get width of this definition (by definition)
+ float width() const { return m_rect.width(); }
+
+ /// Get height of this definition (by definition)
+ float height() const { return m_rect.height(); }
+
+ /// Create an instance of this character
+ character* create_character_instance(character* parent, int id);
+
+ /// Initialize from SWF input stream (tag 37)
+ void read(stream* in, int tag_type, movie_definition* m);
+
+ /// Return a reference to the default text associated
+ /// with this EditText definition.
+ const tu_string& get_default_text() const {
+ return m_default_text;
+ }
+
+ /// Return a reference to the default name for
+ /// instances of this EditText definition. (?)
+ const tu_string& get_default_name() const {
+ return m_default_name;
+ }
+
+ /// \brief
+ /// Return the maximum length of text this widget
+ /// can hold.
+ int get_max_length() const {
+ return m_max_length;
+ }
+
+ /// Get boundaries of this movie
+ //
+ /// Return a reference to private space, copy
+ /// it if you need it for longer then this
+ /// object's lifetime.
+ ///
+ const rect& get_bounds() const {
+ return m_rect;
+ }
+
+ /// Get right margin in twips
+ uint16_t get_right_margin() const {
+ return m_right_margin;
+ }
+
+ /// Get left margin in twips
+ uint16_t get_left_margin() const {
+ return m_left_margin;
+ }
+
+ /// Get indentation in twips
+ uint16_t get_indent() const {
+ return m_indent;
+ }
+
+ /// Get height of font in twips.
+ // @@ what if has_font is false ??
+ uint16_t get_font_height() const {
+ return m_text_height;
+ }
+
+ /// Get font.
+ //
+ /// Note: use add_ref() on the return if you need to keep
+ /// it alive after this definition gets destructed.
+ ///
+ const font* get_font();
+
+ /// Get color of the text
+ const rgba& get_text_color() const {
+ return m_color;
+ }
+
+ /// \brief
+ /// Get extra space between lines (in twips).
+ //
+ /// This is in addition to default font line spacing.
+ uint16_t get_leading() const {
+ return m_leading;
+ }
+
+ /// Get text alignment
+ alignment get_alignment() const {
+ return m_alignment;
+ }
+
+ /// Is border requested ?
+ bool has_border() const {
+ return m_border;
+ }
+
+ /// Word wrap requested ?
+ bool do_word_wrap() const {
+ return m_word_wrap;
+ }
+
+ /// Get root movie definition
+ movie_definition* get_root_def() {
+ return m_root_def;
+ }
+
+ bool get_readonly() const
+ {
+ return m_readonly;
+ }
+
+private:
+
+ /// Root movie_definition
+ movie_definition* m_root_def;
+
+ rect m_rect;
+ tu_string m_default_name;
+ text_format m_format;
+ bool m_word_wrap;
+ bool m_multiline;
+ /// show asterisks instead of actual characters
+ bool m_password;
+ bool m_readonly;
+ /// resize our bound to fit the text
+ bool m_auto_size;
+ bool m_no_select;
+
+ /// forces white background and black border.
+ /// silly, but sometimes used
+ bool m_border;
+
+ /// Allowed HTML (from Alexi's SWF Reference).
+ //
+ /// <a href=url target=targ>...</a> -- hyperlink
+ /// <b>...</b> -- bold
+ /// <br> -- line break
+ /// <font face=name size=[+|-][0-9]+ color=#RRGGBB>...</font> -- font
change; size in TWIPS
+ /// <i>...</i> -- italic
+ /// <li>...</li> -- list item
+ /// <p>...</p> -- paragraph
+ /// <tab> -- insert tab
+ /// <TEXTFORMAT> </TEXTFORMAT>
+ /// [ BLOCKINDENT=[0-9]+ ]
+ /// [ INDENT=[0-9]+ ]
+ /// [ LEADING=[0-9]+ ]
+ /// [ LEFTMARGIN=[0-9]+ ]
+ /// [ RIGHTMARGIN=[0-9]+ ]
+ /// [ TABSTOPS=[0-9]+{,[0-9]+} ]
+ ///
+ /// Change the different parameters as indicated. The
+ /// sizes are all in TWIPs. There can be multiple
+ /// positions for the tab stops. These are seperated by
+ /// commas.
+ /// <U>...</U> -- underline
+ ///
+ bool m_html;
+
+
+
+ /// \brief
+ /// When true, use specified SWF internal font.
+ /// Otherwise, renderer picks a default font
+ bool m_use_outlines;
+
+ int m_font_id;
+ font* m_font;
+
+ /// height of font text, in twips
+ uint16_t m_text_height;
+
+ /// Text color
+ rgba m_color;
+
+ /// Maximum length of text this widget can display (number of chars?)
+ int m_max_length;
+
+ alignment m_alignment;
+
+ /// extra space between box's left border and text (in twips)
+ uint16_t m_left_margin;
+ //float m_left_margin;
+
+ /// extra space between box's right border and text (in twips)
+ uint16_t m_right_margin;
+ //float m_right_margin;
+
+ /// how much to indent the first line of multiline text (in twips)
+ uint16_t m_indent;
+ //float m_indent;
+
+ /// \brief
+ /// Extra space between lines
+ /// (in addition to default font line spacing)
+ uint16_t m_leading;
+
+ /// The default text to be displayed
+ tu_string m_default_text;
+
+};
+
+} // namespace gnash
+
+#endif // _GNASH_EDIT_TEXT_CHARACTER_DEF_H_
Index: server/parser/movie_def_impl.cpp
===================================================================
RCS file: server/parser/movie_def_impl.cpp
diff -N server/parser/movie_def_impl.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/movie_def_impl.cpp 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,1024 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include <iostream>
+#include <string>
+
+#include "movie_def_impl.h"
+#include "movie_definition.h" // for inheritance
+#include "movie_instance.h"
+#include "tu_file.h"
+#include "zlib_adapter.h"
+#include "stream.h"
+#include "jpeg.h"
+#include "fontlib.h"
+#include "font.h"
+#include "log.h"
+//#include "Sprite.h"
+#include "sprite_instance.h"
+#include "render.h"
+#include "bitmap_character_def.h"
+#include "smart_ptr.h"
+#include "swf/TagLoadersTable.h"
+#include "execute_tag.h"
+#include "movie_root.h"
+
+using namespace std;
+
+// Increment this when the cache data format changes.
+#define CACHE_FILE_VERSION 4
+
+// If != 0 this is the number of frames to load at each iteration
+// of the main loop. Loading in chunks greatly speeds the process up
+#define FRAMELOAD_CHUNK 0
+
+// Debug frames load
+#undef DEBUG_FRAMES_LOAD
+
+// Define this this to load movies using a separate thread
+// (undef and it will fully load a movie before starting to play it)
+#define LOAD_MOVIES_IN_A_SEPARATE_THREAD 1
+
+// Debug threads locking
+#undef DEBUG_THREADS_LOCKING
+
+namespace gnash
+{
+
+#ifdef USE_SDL_THREADS
+
+MovieLoader::MovieLoader(movie_def_impl& md)
+ :
+ _waiting_for_frame(0),
+ _movie_def(md)
+{
+ _frame_reached_condition = SDL_CreateCond();
+ _mutex = SDL_CreateMutex();
+}
+
+MovieLoader::~MovieLoader()
+{
+ SDL_DestroyMutex(_mutex);
+ SDL_DestroyCond(_frame_reached_condition);
+}
+
+int MovieLoader::execute(void* arg)
+{
+ movie_def_impl* md = static_cast<movie_def_impl*>(arg);
+ md->read_all_swf();
+ return 0;
+}
+
+bool MovieLoader::start()
+{
+ _thread = SDL_CreateThread(execute, &_movie_def);
+ if (_thread == NULL)
+ {
+ return false;
+ }
+ return true;
+}
+
+void MovieLoader::signal_frame_loaded(size_t frameno)
+{
+ if (_waiting_for_frame &&
+ frameno >= _waiting_for_frame )
+ {
+ SDL_CondSignal(_frame_reached_condition);
+ }
+}
+
+void MovieLoader::wait_for_frame(size_t framenum)
+{
+
+ lock();
+
+ if (_movie_def.get_loading_frame() < framenum)
+ {
+ //log_msg("Waiting for frame %u to load", framenum);
+
+ assert(_waiting_for_frame == 0);
+ _waiting_for_frame = framenum;
+
+ do
+ {
+ SDL_CondWait(_frame_reached_condition, _mutex);
+ }
+ while (_movie_def.get_loading_frame() < framenum);
+
+ _waiting_for_frame = 0;
+
+ //log_msg("Done waiting (frame %u/%u loaded)",
+ // _movie_def.get_loading_frame(),
+ // _movie_def.get_frame_count());
+ }
+
+ unlock();
+}
+
+void MovieLoader::lock()
+{
+ if ( -1 == SDL_mutexP(_mutex) )
+ {
+ log_error("Error unlocking MovieLoader");
+ }
+}
+
+void MovieLoader::unlock()
+{
+ if ( -1 == SDL_mutexV(_mutex) )
+ {
+ log_error("Error unlocking MovieLoader");
+ }
+}
+
+#else
+
+MovieLoader::MovieLoader(movie_def_impl& md)
+ :
+ _waiting_for_frame(0),
+ _movie_def(md)
+{
+ pthread_cond_init(&_frame_reached_condition, NULL);
+ pthread_mutex_init(&_mutex, NULL);
+}
+
+MovieLoader::~MovieLoader()
+{
+ if ( pthread_cond_destroy(&_frame_reached_condition) != 0 )
+ {
+ log_error("Error destroying MovieLoader condition");
+ }
+
+ if ( pthread_mutex_destroy(&_mutex) != 0 )
+ {
+ log_error("Error destroying MovieLoader mutex");
+ }
+}
+
+void*
+MovieLoader::execute(void* arg)
+{
+ movie_def_impl* md = static_cast<movie_def_impl*>(arg);
+ md->read_all_swf();
+ // maybe this frees all resources and that's bad !
+ //pthread_exit(NULL);
+
+ /* Better to cancel yourself methinks: 'man 3p pthread_cancel' */
+ pthread_cancel(pthread_self());
+ pthread_testcancel();
+ return NULL;
+}
+
+bool
+MovieLoader::start()
+{
+ if ( pthread_create(&_thread, NULL, execute, &_movie_def) )
+ {
+ return false;
+ }
+
+ // should set some mutexes ?
+
+ return true;
+}
+
+void
+MovieLoader::signal_frame_loaded(size_t frameno)
+{
+ if (_waiting_for_frame &&
+ frameno >= _waiting_for_frame )
+ {
+ pthread_cond_signal(&_frame_reached_condition);
+ }
+}
+
+void
+MovieLoader::lock()
+{
+
+#ifdef DEBUG_THREADS_LOCKING
+ // debugging
+ if ( pthread_equal(pthread_self(), _thread) ) {
+ log_msg("MovieLoader locking itself");
+ } else {
+ log_msg("MovieLoader being locked by another thread");
+ }
+#endif
+
+ if ( pthread_mutex_lock(&_mutex) != 0 )
+ {
+ log_error("Error locking MovieLoader");
+ }
+
+#ifdef DEBUG_THREADS_LOCKING
+ // debugging
+ if ( pthread_equal(pthread_self(), _thread) ) {
+ log_msg("MovieLoader locked by itself");
+ } else {
+ log_msg("MovieLoader locked by another thread");
+ }
+#endif
+}
+
+void
+MovieLoader::unlock()
+{
+
+#ifdef DEBUG_THREADS_LOCKING
+ // debugging
+ if ( pthread_equal(pthread_self(), _thread) ) {
+ log_msg("MovieLoader unlocking itself");
+ } else {
+ log_msg("MovieLoader being unlocked by another thread");
+ }
+#endif
+
+ if ( pthread_mutex_unlock(&_mutex) != 0 )
+ {
+ log_error("Error unlocking MovieLoader");
+ }
+
+#ifdef DEBUG_THREADS_LOCKING
+ // debugging
+ if ( pthread_equal(pthread_self(), _thread) ) {
+ log_msg("MovieLoader unlocked itself");
+ } else {
+ log_msg("MovieLoader unlocked by another thread");
+ }
+#endif
+}
+
+void
+MovieLoader::wait_for_frame(size_t framenum)
+{
+
+ // lock the loader so we can rely on m_loading_frame
+ lock();
+
+ if ( _movie_def.get_loading_frame() < framenum )
+ {
+ assert(_waiting_for_frame == 0);
+ _waiting_for_frame = framenum;
+ pthread_cond_wait(&_frame_reached_condition, &_mutex);
+ _waiting_for_frame = 0;
+ }
+
+ unlock();
+}
+
+#endif // PTHREAD MovieLoader
+
+
+//
+// some utility stuff
+//
+
+void dump_tag_bytes(stream* in)
+ // Log the contents of the current tag, in hex.
+{
+ static const int ROW_BYTES = 16;
+ char row_buf[ROW_BYTES];
+ int row_count = 0;
+
+ while(in->get_position() < in->get_tag_end_position())
+ {
+ int c = in->read_u8();
+ log_msg("%02X", c);
+
+ if (c < 32) c = '.';
+ if (c > 127) c = '.';
+ row_buf[row_count] = c;
+
+ row_count++;
+ if (row_count >= ROW_BYTES)
+ {
+ log_msg(" ");
+ for (int i = 0; i < ROW_BYTES; i++)
+ {
+ log_msg("%c", row_buf[i]);
+ }
+
+ log_msg("\n");
+ row_count = 0;
+ }
+ else
+ {
+ log_msg(" ");
+ }
+ }
+
+ if (row_count > 0)
+ {
+ log_msg("\n");
+ }
+}
+
+
+//
+// progress callback stuff (from Vitaly)
+//
+progress_callback s_progress_function = NULL;
+
+// Host calls this to register a function for progress bar handling
+// during loading movies.
+void
+register_progress_callback(progress_callback progress_handle)
+{
+ s_progress_function = progress_handle;
+}
+
+//
+// movie_def_impl
+//
+
+movie_def_impl::movie_def_impl(create_bitmaps_flag cbf,
+ create_font_shapes_flag cfs)
+ :
+ _tag_loaders(s_tag_loaders), // FIXME: use a class-static
TagLoadersTable for movie_def_impl
+ m_create_bitmaps(cbf),
+ m_create_font_shapes(cfs),
+ m_frame_rate(30.0f),
+ m_frame_count(0u),
+ m_version(0),
+ m_loading_frame(0u),
+ _loaded_bytes(0u),
+ m_jpeg_in(0),
+ _loader(*this)
+{
+}
+
+movie_def_impl::~movie_def_impl()
+{
+ // Release our playlist data.
+ {for (int i = 0, n = m_playlist.size(); i < n; i++)
+ {
+ for (int j = 0, m = m_playlist[i].size(); j < m; j++)
+ {
+ delete m_playlist[i][j];
+ }
+ }}
+
+ // Release init action data.
+ {for (size_t i = 0, n = m_init_action_list.size(); i < n; i++)
+ {
+ for (size_t j = 0, m = m_init_action_list[i].size(); j < m; j++)
+ {
+ delete m_init_action_list[i][j];
+ }
+ }}
+
+ // It's supposed to be cleaned up in read()
+ // TODO: join with loader thread instead ?
+ //assert(m_jpeg_in.get() == NULL);
+}
+
+bool movie_def_impl::in_import_table(int character_id)
+{
+ for (int i = 0, n = m_imports.size(); i < n; i++)
+ {
+ if (m_imports[i].m_character_id == character_id)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void movie_def_impl::visit_imported_movies(import_visitor* visitor)
+{
+ stringi_hash<bool> visited; // ugh!
+
+ for (int i = 0, n = m_imports.size(); i < n; i++)
+ {
+ const import_info& inf = m_imports[i];
+ if (visited.find(inf.m_source_url) == visited.end())
+ {
+ // Call back the visitor.
+ visitor->visit(inf.m_source_url.c_str());
+ visited[inf.m_source_url] = true;
+ }
+ }
+}
+
+void movie_def_impl::resolve_import(const char* source_url, movie_definition*
source_movie)
+{
+ // @@ should be safe, but how can we verify
+ // it? Compare a member function pointer, or
+ // something?
+ movie_def_impl* def_impl = static_cast<movie_def_impl*>(source_movie);
+ movie_definition* def = static_cast<movie_definition*>(def_impl);
+
+ // Iterate in reverse, since we remove stuff along the way.
+ for (int i = m_imports.size() - 1; i >= 0; i--)
+ {
+ const import_info& inf = m_imports[i];
+ if (inf.m_source_url == source_url)
+ {
+ // Do the import.
+ smart_ptr<resource> res =
def->get_exported_resource(inf.m_symbol);
+ bool imported = true;
+
+ if (res == NULL)
+ {
+ log_error("import error: resource '%s' is not
exported from movie '%s'\n",
+ inf.m_symbol.c_str(), source_url);
+ }
+ else if (font* f = res->cast_to_font())
+ {
+ // Add this shared font to our fonts.
+ add_font(inf.m_character_id, f);
+ imported = true;
+ }
+ else if (character_def* ch = res->cast_to_character_def())
+ {
+ // Add this character to our characters.
+ add_character(inf.m_character_id, ch);
+ imported = true;
+ }
+ else
+ {
+ log_error("import error: resource '%s' from movie
'%s' has unknown type\n",
+ inf.m_symbol.c_str(), source_url);
+ }
+
+ if (imported)
+ {
+ m_imports.erase(m_imports.begin() + i);
+
+ // Hold a ref, to keep this source
movie_definition alive.
+ m_import_source_movies.push_back(source_movie);
+ }
+ }
+ }
+}
+
+void movie_def_impl::add_character(int character_id, character_def* c)
+{
+ assert(c);
+ _dictionary.add_character(character_id, c);
+}
+
+character_def*
+movie_def_impl::get_character_def(int character_id)
+{
+#ifndef NDEBUG
+ // make sure character_id is resolved
+ if (in_import_table(character_id))
+ {
+ log_error("get_character_def(): character_id %d is still waiting
to be imported\n",
+ character_id);
+ }
+#endif // not NDEBUG
+
+ smart_ptr<character_def> ch = _dictionary.get_character(character_id);
+ assert(ch == NULL || ch->get_ref_count() > 1);
+ return ch.get_ptr(); // mm... why don't we return the smart_ptr?
+}
+
+void movie_def_impl::add_font(int font_id, font* f)
+{
+ assert(f);
+ m_fonts.add(font_id, f);
+}
+
+font* movie_def_impl::get_font(int font_id)
+{
+#ifndef NDEBUG
+ // make sure font_id is resolved
+ if (in_import_table(font_id))
+ {
+ log_error("get_font(): font_id %d is still waiting to be
imported\n",
+ font_id);
+ }
+#endif // not NDEBUG
+
+ smart_ptr<font> f;
+ m_fonts.get(font_id, &f);
+ assert(f == NULL || f->get_ref_count() > 1);
+ return f.get_ptr();
+}
+
+bitmap_character_def* movie_def_impl::get_bitmap_character(int character_id)
+{
+ smart_ptr<bitmap_character_def> ch;
+ m_bitmap_characters.get(character_id, &ch);
+ assert(ch == NULL || ch->get_ref_count() > 1);
+ return ch.get_ptr();
+}
+
+void movie_def_impl::add_bitmap_character(int character_id,
bitmap_character_def* ch)
+{
+ assert(ch);
+ //log_msg("Add bitmap character %d", character_id);
+ m_bitmap_characters.add(character_id, ch);
+
+ add_bitmap_info(ch->get_bitmap_info());
+}
+
+sound_sample* movie_def_impl::get_sound_sample(int character_id)
+{
+ smart_ptr<sound_sample> ch;
+ m_sound_samples.get(character_id, &ch);
+ assert(ch == NULL || ch->get_ref_count() > 1);
+ return ch.get_ptr();
+}
+
+void movie_def_impl::add_sound_sample(int character_id, sound_sample* sam)
+{
+ assert(sam);
+ log_msg("Add sound sample %d", character_id);
+ m_sound_samples.add(character_id, sam);
+}
+
+
+// Read a .SWF movie.
+bool
+movie_def_impl::read(tu_file* in, const std::string& url)
+{
+
+ // we only read a movie once (well, headers at least)
+ assert(_str.get() == NULL);
+
+ if ( url == "" ) _url = "<anonymous>";
+ else _url = url;
+
+ uint32_t file_start_pos = in->get_position();
+ uint32_t header = in->read_le32();
+ m_file_length = in->read_le32();
+ _swf_end_pos = file_start_pos + m_file_length;
+
+ m_version = (header >> 24) & 255;
+ if ((header & 0x0FFFFFF) != 0x00535746
+ && (header & 0x0FFFFFF) != 0x00535743)
+ {
+ // ERROR
+ log_error("gnash::movie_def_impl::read() -- "
+ "file does not start with a SWF header!\n");
+ return false;
+ }
+ bool compressed = (header & 255) == 'C';
+
+ IF_VERBOSE_PARSE(
+ log_parse("version = %d, file_length = %d",
+ m_version, m_file_length);
+ );
+
+ tu_file* original_in = NULL;
+ if (compressed)
+ {
+#if TU_CONFIG_LINK_TO_ZLIB == 0
+ log_error("movie_def_impl::read(): unable to read "
+ "zipped SWF data; TU_CONFIG_LINK_TO_ZLIB is 0\n");
+ return false;
+#endif
+
+ IF_VERBOSE_PARSE(
+ log_parse("file is compressed.");
+ );
+
+ original_in = in;
+
+ // Uncompress the input as we read it.
+ _zlib_file.reset(zlib_adapter::make_inflater(original_in));
+ in = _zlib_file.get();
+
+ // Subtract the size of the 8-byte header, since
+ // it's not included in the compressed
+ // stream length.
+ _swf_end_pos = m_file_length - 8;
+ }
+
+ //stream str(in);
+ _str.reset(new stream(in));
+
+ m_frame_size.read(_str.get());
+ m_frame_rate = _str->read_u16() / 256.0f;
+ m_frame_count = _str->read_u16();
+
+ // hack
+ // Vitaly: I am not assured that it correctly
+ m_frame_count = (m_frame_count == 0) ? 1 : m_frame_count;
+
+ m_playlist.resize(m_frame_count);
+ m_init_action_list.resize(m_frame_count);
+
+ IF_VERBOSE_PARSE(
+ m_frame_size.print();
+ log_parse("frame rate = %f, frames = %d",
+ m_frame_rate, m_frame_count);
+ );
+
+#ifdef LOAD_MOVIES_IN_A_SEPARATE_THREAD
+
+ // Start the loading frame
+ if ( ! _loader.start() )
+ {
+ log_error("Could not start loading thread");
+ }
+
+ // Wait until 'startup_frames' have been loaded
+#if 1
+ size_t startup_frames = 1;
+#else
+ size_t startup_frames = m_frame_count;
+#endif
+ ensure_frame_loaded(startup_frames);
+
+#else // undef LOAD_MOVIES_IN_A_SEPARATE_THREAD
+
+ read_all_swf();
+#endif
+
+// Can't delete here as we will keep reading from it while playing
+// FIXME: remove this at end of reading (or in destructor)
+#if 0
+ if (original_in)
+ {
+ // Done with the zlib_adapter.
+ delete in;
+ }
+#endif
+
+ return true;
+}
+
+
+// 1-based frame number
+bool
+movie_def_impl::ensure_frame_loaded(size_t framenum)
+{
+ //log_msg("Waiting for frame %u to be loaded", framenum);
+ _loader.wait_for_frame(framenum);
+ //log_msg("Condition reached (m_loading_frame=%u)", m_loading_frame);
+
+
+ // TODO: return false on timeout
+ return true;
+}
+
+
+/* movie_def_impl */
+void movie_def_impl::get_owned_fonts(std::vector<font*>* fonts)
+ // Fill up *fonts with fonts that we own.
+{
+ assert(fonts);
+ fonts->resize(0);
+
+ std::vector<int> font_ids;
+
+ for (hash<int, smart_ptr<font> >::iterator it = m_fonts.begin();
+ it != m_fonts.end();
+ ++it)
+ {
+ font* f = it->second.get_ptr();
+ if (f->get_owning_movie() == this)
+ {
+ // Sort by character id, so the ordering is
+ // consistent for cache read/write.
+ int id = it->first;
+
+ // Insert in correct place.
+ unsigned int insert;
+ for (insert = 0; insert < font_ids.size(); insert++)
+ {
+ if (font_ids[insert] > id)
+ {
+ // We want to insert here.
+ break;
+ }
+ }
+ fonts->insert(fonts->begin() + insert, f);
+ font_ids.insert(font_ids.begin() + insert, id);
+ }
+ }
+}
+
+
+/* movie_def_impl */
+void movie_def_impl::generate_font_bitmaps()
+ // Generate bitmaps for our fonts, if necessary.
+{
+ // Collect list of fonts.
+ std::vector<font*> fonts;
+ get_owned_fonts(&fonts);
+ fontlib::generate_font_bitmaps(fonts, this);
+}
+
+void
+movie_def_impl::output_cached_data(tu_file* out, const cache_options& options)
+{
+ // Write a little header.
+ char header[5];
+ strcpy(header, "gscX");
+ header[3] = CACHE_FILE_VERSION;
+ compiler_assert(CACHE_FILE_VERSION < 256);
+
+ out->write_bytes(header, 4);
+
+ // Write font data.
+ std::vector<font*> fonts;
+ get_owned_fonts(&fonts);
+ fontlib::output_cached_data(out, fonts, this, options);
+
+ // Write character data.
+ {
+
+ for ( CharacterDictionary::iterator
+ it = _dictionary.begin(), itEnd = _dictionary.end();
+ it != itEnd;
+ ++it )
+ {
+ out->write_le16(it->first);
+ it->second->output_cached_data(out, options);
+ }
+
+#if 0
+ for (hash<int, smart_ptr<character_def> >::iterator it =
m_characters.begin();
+ it != m_characters.end();
+ ++it)
+ {
+ out->write_le16(it->first);
+ it->second->output_cached_data(out, options);
+ }
+#endif
+ }
+
+ out->write_le16((int16_t) -1); // end of characters marker
+}
+
+
+void
+movie_def_impl::input_cached_data(tu_file* in)
+{
+ // Read the header & check version.
+ unsigned char header[4];
+ in->read_bytes(header, 4);
+ if (header[0] != 'g' || header[1] != 's' || header[2] != 'c')
+ {
+ log_error("cache file does not have the correct format;
skipping\n");
+ return;
+ }
+ else if (header[3] != CACHE_FILE_VERSION)
+ {
+ log_error(
+ "cached data is version %d, but we require version %d;
skipping\n",
+ int(header[3]), CACHE_FILE_VERSION);
+ return;
+ }
+
+ // Read the cached font data.
+ std::vector<font*> fonts;
+ get_owned_fonts(&fonts);
+ fontlib::input_cached_data(in, fonts, this);
+
+ // Read the cached character data.
+ for (;;)
+ {
+ if (in->get_error() != TU_FILE_NO_ERROR)
+ {
+ log_error("error reading cache file (characters);
skipping\n");
+ return;
+ }
+ if (in->get_eof())
+ {
+ log_error("unexpected eof reading cache file (characters);
skipping\n");
+ return;
+ }
+
+ int16_t id = in->read_le16();
+ if (id == (int16_t) -1) { break; } // done
+
+ smart_ptr<character_def> ch = _dictionary.get_character(id);
+ //m_characters.get(id, &ch);
+ if (ch != NULL)
+ {
+ ch->input_cached_data(in);
+ }
+ else
+ {
+ log_error("sync error in cache file (reading characters)!
"
+ "Skipping rest of cache data.\n");
+ return;
+ }
+ }
+}
+
+movie_interface*
+movie_def_impl::create_instance()
+{
+ movie_root* m = new movie_root(this);
+ assert(m);
+
+ sprite_instance* root_movie = new movie_instance(this, m, NULL);
+ assert(root_movie);
+
+ root_movie->set_name("_root");
+ m->set_root_movie(root_movie);
+
+ // @@ somewhere in here I *might* add _url variable
+ // (or is it a member?)
+
+ m->add_ref();
+
+ root_movie->execute_frame_tags(0); // create _root dlist
+
+ return m;
+}
+
+
+//
+// CharacterDictionary
+//
+
+void
+CharacterDictionary::dump_chars() const
+{
+ for ( const_iterator it=begin(), endIt=end();
+ it != endIt; ++it )
+ {
+ log_msg("Character %d @ %p", it->first, it->second.get_ptr());
+ //character_def* cdef = it->second;
+ }
+}
+
+smart_ptr<character_def>
+CharacterDictionary::get_character(int id)
+{
+ container::iterator it = _map.find(id);
+ if ( it == _map.end() )
+ {
+ log_msg("Could not find char %d, dump is:", id);
+ dump_chars();
+ return smart_ptr<character_def>();
+ }
+ else return it->second;
+}
+
+void
+CharacterDictionary::add_character(int id, smart_ptr<character_def> c)
+{
+ //log_msg("CharacterDictionary: add char %d", id);
+ _map[id] = c;
+ //dump_chars();
+}
+
+// Load next chunk of this sprite frames.
+// This is possibly better defined in movie_definition
+void
+movie_def_impl::load_next_frame_chunk()
+{
+
+ size_t framecount = get_frame_count();
+ size_t lastloaded = get_loading_frame();
+
+ // nothing to do
+ if ( lastloaded == framecount ) return;
+
+ size_t nextframe = lastloaded+1;
+
+#if FRAMELOAD_CHUNK
+ nextframe += FRAMELOAD_CHUNK; // load in chunks of 10 frames
+ if ( nextframe > framecount ) nextframe = framecount;
+#endif
+ //log_msg("Framecount: %u, Lastloaded: %u", framecount, lastloaded);
+ if ( nextframe <= framecount )
+ {
+#ifdef DEBUG_FRAMES_LOAD // debugging
+ log_msg("Ensure load of frame %u/%u (last loaded is: %u)",
+ nextframe, framecount, lastloaded);
+#endif
+ if ( ! ensure_frame_loaded(nextframe) )
+ {
+ log_error("Could not advance to frame %d!",
+ nextframe);
+ // these kind of errors should be handled by callers
+ assert(0);
+ }
+ }
+#ifdef DEBUG_FRAMES_LOAD
+ else
+ {
+ log_msg("No more frames to load. Framecount: %u, Lastloaded:
%u, next to load: %u", framecount, lastloaded, nextframe);
+ }
+#endif
+}
+
+void
+movie_def_impl::read_all_swf()
+{
+ assert(_str.get() != NULL);
+
+ stream& str=*_str;
+
+ //size_t it=0;
+ while ( (uint32_t) str.get_position() < _swf_end_pos )
+ {
+ // Get exclusive lock on loader, to avoid
+ // race conditions with wait_for_frame
+ _loader.lock();
+
+ //log_msg("Loading thread iteration %u", it++);
+
+ SWF::tag_type tag_type = str.open_tag();
+
+ if (s_progress_function != NULL)
+ {
+ s_progress_function((uint32_t)str.get_position(),
+ _swf_end_pos);
+ }
+
+ SWF::TagLoadersTable::loader_function lf = NULL;
+ //log_parse("tag_type = %d\n", tag_type);
+ if (tag_type == SWF::SHOWFRAME)
+ {
+ // show frame tag -- advance to the next frame.
+
+ IF_VERBOSE_PARSE(
+ log_parse(" show_frame\n");
+ );
+
+ ++m_loading_frame;
+
+ // signal load of frame
+ _loader.signal_frame_loaded(m_loading_frame);
+
+#if DEBUG_FRAMES_LOAD
+ log_msg("Loaded frame %u/%u",
+ m_loading_frame, m_frame_count);
+#endif
+ }
+ else if (_tag_loaders.get(tag_type, &lf))
+ {
+ // call the tag loader. The tag loader should add
+ // characters or tags to the movie data structure.
+ (*lf)(&str, tag_type, this);
+ }
+ else
+ {
+ // no tag loader for this tag type.
+ log_error("*** no tag loader for type %d
(movie)",
+ tag_type);
+ dump_tag_bytes(&str);
+ }
+
+ str.close_tag();
+
+ if (tag_type == SWF::END)
+ {
+ if ((unsigned int) str.get_position() != _swf_end_pos)
+ {
+ // Safety break, so we don't read past
+ // the end of the movie.
+ log_warning("hit stream-end tag, "
+ "but not at the advertised SWF end; "
+ "stopping for safety.");
+ _loader.unlock();
+ break;
+ }
+ }
+ _loader.unlock();
+
+ }
+
+}
+
+} // namespace gnash
+
Index: server/parser/movie_def_impl.h
===================================================================
RCS file: server/parser/movie_def_impl.h
diff -N server/parser/movie_def_impl.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/movie_def_impl.h 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,570 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+
+#ifndef GNASH_MOVIE_DEF_IMPL_H
+#define GNASH_MOVIE_DEF_IMPL_H
+
+#include "container.h"
+#include "smart_ptr.h"
+#include "button.h" // for mouse_button_state
+#include "timers.h" // for Timer
+#include "fontlib.h"
+#include "font.h"
+#include "jpeg.h"
+#include "tu_file.h"
+#include "movie_definition.h" // for inheritance
+#include "character_def.h" // for smart_ptr visibility of dtor
+#include "bitmap_character_def.h" // for smart_ptr visibility of dtor
+#include "resource.h" // for smart_ptr visibility of dtor
+#include "stream.h" // for get_bytes_loaded
+
+#include <map> // for CharacterDictionary
+#include <string>
+#include <memory> // for auto_ptr
+
+// We'd avoid SDL threads if possible. Please define the macro below
+// if you experience problems and report the difference on gnash-dev
+#undef REALLY_USE_SDL_THREADS
+
+#ifdef REALLY_USE_SDL_THREADS
+#ifdef HAVE_SDL_H
+# define USE_SDL_THREADS 1
+#endif
+#endif
+
+#ifdef USE_SDL_THREADS
+# include "SDL.h"
+# include "SDL_thread.h"
+#endif
+
+
+namespace gnash
+{
+
+// Forward declarations
+class import_info;
+class movie_def_impl;
+class movie_root;
+
+//
+// Helper for movie_def_impl
+//
+
+class import_info
+{
+ friend class movie_def_impl;
+
+ tu_string m_source_url;
+ int m_character_id;
+ tu_string m_symbol;
+
+ import_info()
+ :
+ m_character_id(-1)
+ {
+ }
+
+ import_info(const char* source, int id, const char* symbol)
+ :
+ m_source_url(source),
+ m_character_id(id),
+ m_symbol(symbol)
+ {
+ }
+};
+
+/// \brief
+/// movie_def_impl helper class handling start and execution of
+/// an SWF loading thread
+///
+class MovieLoader
+{
+
+public:
+
+ MovieLoader(movie_def_impl& md);
+
+ ~MovieLoader();
+
+ /// Start loading thread.
+ //
+ /// The associated movie_def_impl instance
+ /// is expected to have already read the SWF
+ /// header and applied a zlib adapter if needed.
+ ///
+ bool start();
+
+ /// Wait for specified frame number (1-based) to be loaded
+ //
+ /// Block caller thread until frame is loaded.
+ ///
+ void wait_for_frame(size_t framenum);
+
+ /// Signal load of given frame number (if anyone waiting for it)
+ void signal_frame_loaded(size_t frameno);
+
+ void lock();
+
+ void unlock();
+
+private:
+
+ size_t _waiting_for_frame;
+ movie_def_impl& _movie_def;
+
+#ifdef USE_SDL_THREADS
+
+ static int execute(void* arg);
+
+ SDL_Thread* _thread;
+ SDL_cond* _frame_reached_condition;
+ SDL_mutex* _mutex;
+
+#else
+
+ pthread_cond_t _frame_reached_condition;
+ pthread_mutex_t _mutex;
+ pthread_t _thread;
+
+ /// Entry point for the actual thread
+ static void *execute(void* arg);
+
+#endif
+
+};
+
+/// The Characters dictionary associated with each SWF file.
+//
+/// This is a set of Characters defined by define tags and
+/// getting assigned a unique ID.
+///
+class CharacterDictionary
+{
+
+public:
+
+ /// The container used by this dictionary
+ //
+ /// It contains pairs of 'int' and 'smart_ptr<character_def>'
+ ///
+ typedef std::map< int, smart_ptr<character_def> > container;
+ //typedef hash< int, smart_ptr<character_def> >container;
+
+ typedef container::iterator iterator;
+
+ typedef container::const_iterator const_iterator;
+
+ /// Get the Character with the given id
+ //
+ /// returns a NULL if the id is unknown.
+ ///
+ smart_ptr<character_def> get_character(int id);
+
+ /// Add a Character assigning it the given id
+ //
+ /// replaces any existing character with the same id
+ ///
+ void add_character(int id, smart_ptr<character_def> c);
+
+ /// Return an iterator to the first dictionary element
+ iterator begin() { return _map.begin(); }
+
+ /// Return a const_iterator to the first dictionary element
+ const_iterator begin() const { return _map.begin(); }
+
+ /// Return an iterator to one-past last dictionary element
+ iterator end() { return _map.end(); }
+
+ /// Return a const_iterator to one-past last dictionary element
+ const_iterator end() const { return _map.end(); }
+
+ /// Dump content of the dictionary (debugging only)
+ void dump_chars(void) const;
+private:
+
+ container _map;
+
+};
+
+
+/// Immutable definition of a movie's contents.
+//
+/// It cannot be played directly, and does not hold
+/// current state; for that you need to call create_instance()
+/// to get a movie instance (gnash::movie_interface).
+///
+class movie_def_impl : public movie_definition
+{
+ /// Characters Dictionary
+ CharacterDictionary _dictionary;
+ //hash<int, smart_ptr<character_def> > m_characters;
+
+ /// Tags loader table
+ SWF::TagLoadersTable& _tag_loaders;
+
+ hash<int, smart_ptr<font> > m_fonts;
+ hash<int, smart_ptr<bitmap_character_def> > m_bitmap_characters;
+ hash<int, smart_ptr<sound_sample> > m_sound_samples;
+ hash<int, smart_ptr<sound_sample> > m_sound_streams;
+
+ /// A list of movie control events for each frame.
+ std::vector<std::vector<execute_tag*> > m_playlist;
+
+ /// Init actions for each frame.
+ std::vector<std::vector<execute_tag*> > m_init_action_list;
+
+ /// 0-based frame #'s
+ stringi_hash<size_t> m_named_frames;
+
+ stringi_hash<smart_ptr<resource> > m_exports;
+
+ /// Items we import.
+ std::vector<import_info> m_imports;
+
+ /// Movies we import from; hold a ref on these,
+ /// to keep them alive
+ std::vector<smart_ptr<movie_definition> > m_import_source_movies;
+
+ /// Bitmaps used in this movie; collected in one place to make
+ /// it possible for the host to manage them as textures.
+ std::vector<smart_ptr<bitmap_info> > m_bitmap_list;
+
+ create_bitmaps_flag m_create_bitmaps;
+ create_font_shapes_flag m_create_font_shapes;
+
+ rect m_frame_size;
+ float m_frame_rate;
+ size_t m_frame_count;
+ int m_version;
+ size_t m_loading_frame;
+ int m_loading_sound_stream;
+ uint32 m_file_length;
+ size_t _loaded_bytes;
+
+ std::auto_ptr<jpeg::input> m_jpeg_in;
+
+ std::string _url;
+
+ std::auto_ptr<stream> _str;
+
+ tu_file* in;
+
+ std::auto_ptr<tu_file> _zlib_file;
+
+ /// swf end position (as read from header)
+ unsigned int _swf_end_pos;
+
+ /// asyncronous SWF loader and parser
+ MovieLoader _loader;
+
+public:
+
+ movie_def_impl(create_bitmaps_flag cbf, create_font_shapes_flag cfs);
+
+ ~movie_def_impl();
+
+ // ...
+ size_t get_frame_count() const { return m_frame_count; }
+ float get_frame_rate() const { return m_frame_rate; }
+ const rect& get_frame_size() const { return m_frame_size; }
+
+ float get_width_pixels() const
+ {
+ return ceilf(TWIPS_TO_PIXELS(m_frame_size.width()));
+ }
+
+ float get_height_pixels() const
+ {
+ return ceilf(TWIPS_TO_PIXELS(m_frame_size.height()));
+ }
+
+ virtual int get_version() const { return m_version; }
+
+ virtual size_t get_loading_frame() const
+ {
+ return m_loading_frame;
+ }
+
+#if 0 // renamed to get_bytes_total
+ uint32 get_file_bytes() const {
+ return m_file_length;
+ }
+#endif
+
+ /// Get number of bytes loaded from input stream
+ size_t get_bytes_loaded() const {
+#if 0 // temporarly disabled because broken
+ uint32 ret = _loaded_bytes;
+#else
+ uint32 ret = m_file_length;
+#endif
+ log_msg("get_bytes_loaded returning %u (loaded frame: %zu/%zu)",
+ ret, m_loading_frame, m_frame_count);
+ return ret;
+ }
+
+ /// Get total number of bytes in input stream
+ size_t get_bytes_total() const {
+ log_msg("get_bytes_total returning %u", m_file_length);
+ return m_file_length;
+ }
+
+ /// Returns DO_CREATE_BITMAPS if we're supposed to
+ /// initialize our bitmap infos, or DO_NOT_INIT_BITMAPS
+ /// if we're supposed to create blank placeholder
+ /// bitmaps (to be init'd later explicitly by the host
+ /// program).
+ virtual create_bitmaps_flag get_create_bitmaps() const
+ {
+ return m_create_bitmaps;
+ }
+
+ /// Returns DO_LOAD_FONT_SHAPES if we're supposed to
+ /// initialize our font shape info, or
+ /// DO_NOT_LOAD_FONT_SHAPES if we're supposed to not
+ /// create any (vector) font glyph shapes, and instead
+ /// rely on precached textured fonts glyphs.
+ virtual create_font_shapes_flag get_create_font_shapes() const
+ {
+ return m_create_font_shapes;
+ }
+
+ /// All bitmap_info's used by this movie should be
+ /// registered with this API.
+ virtual void add_bitmap_info(bitmap_info* bi)
+ {
+ m_bitmap_list.push_back(bi);
+ }
+
+ virtual int get_bitmap_info_count() const
+ {
+ return m_bitmap_list.size();
+ }
+
+ virtual bitmap_info* get_bitmap_info(int i) const
+ {
+ return m_bitmap_list[i].get_ptr();
+ }
+
+ /// Expose one of our resources under the given symbol,
+ /// for export. Other movies can import it.
+ virtual void export_resource(const tu_string& symbol,
+ resource* res)
+ {
+ // SWF sometimes exports the same thing more than once!
+ m_exports[symbol] = res;
+ }
+
+ /// Get the named exported resource, if we expose it.
+ /// Otherwise return NULL.
+ virtual smart_ptr<resource> get_exported_resource(const tu_string&
symbol)
+ {
+ smart_ptr<resource> res;
+ m_exports.get(symbol, &res);
+ return res;
+ }
+
+ /// Adds an entry to a table of resources that need to
+ /// be imported from other movies. Client code must
+ /// call resolve_import() later, when the source movie
+ /// has been loaded, so that the actual resource can be
+ /// used.
+ virtual void add_import(const char* source_url, int id, const char*
symbol)
+ {
+ assert(in_import_table(id) == false);
+
+ m_imports.push_back(import_info(source_url, id, symbol));
+ }
+
+ /// Debug helper; returns true if the given
+ /// character_id is listed in the import table.
+ bool in_import_table(int character_id);
+
+ /// Calls back the visitor for each movie that we
+ /// import symbols from.
+ virtual void visit_imported_movies(import_visitor* visitor);
+
+ /// Grabs the stuff we want from the source movie.
+ virtual void resolve_import(const char* source_url,
+ movie_definition* source_movie);
+
+ void add_character(int character_id, character_def* c);
+
+ /// \brief
+ /// Return a character from the dictionary
+ /// NOTE: call add_ref() on the return or put in a smart_ptr<>
+ /// TODO: return a smart_ptr<> directly...
+ ///
+ character_def* get_character_def(int character_id);
+
+ /// Returns 0-based frame #
+ bool get_labeled_frame(const char* label, size_t* frame_number)
+ {
+ return m_named_frames.get(label, frame_number);
+ }
+
+ void add_font(int font_id, font* f);
+ font* get_font(int font_id);
+ bitmap_character_def* get_bitmap_character(int character_id);
+ void add_bitmap_character(int character_id, bitmap_character_def*
ch);
+ sound_sample* get_sound_sample(int character_id);
+ virtual void add_sound_sample(int character_id, sound_sample* sam);
+ virtual void set_loading_sound_stream_id(int id) {
m_loading_sound_stream = id; }
+ int get_loading_sound_stream_id() { return
m_loading_sound_stream; }
+
+ /// Add an execute_tag to this movie_definition's playlist
+ void add_execute_tag(execute_tag* e)
+ {
+ assert(e);
+ m_playlist[m_loading_frame].push_back(e);
+ }
+
+ /// Need to execute the given tag before entering the
+ /// currently-loading frame for the first time.
+ ///
+ /// @@ AFAIK, the sprite_id is totally pointless -- correct?
+ //void add_init_action(int sprite_id, execute_tag* e)
+ void add_init_action(execute_tag* e)
+ {
+ assert(e);
+ m_init_action_list[m_loading_frame].push_back(e);
+ }
+
+ /// Labels the frame currently being loaded with the
+ /// given name. A copy of the name string is made and
+ /// kept in this object.
+ void add_frame_name(const char* name)
+ {
+ assert(m_loading_frame < m_frame_count);
+
+ tu_string n = name;
+
+ if (m_named_frames.get(n, NULL) == false) //
frame should not already have a name (?)
+ {
+ m_named_frames.add(n, m_loading_frame); // stores
0-based frame #
+ }
+ }
+
+ /// Set an input object for later loading DefineBits
+ /// images (JPEG images without the table info).
+ void set_jpeg_loader(std::auto_ptr<jpeg::input> j_in)
+ {
+ assert(m_jpeg_in.get() == NULL);
+ m_jpeg_in = j_in;
+ }
+
+ /// Get the jpeg input loader, to load a DefineBits
+ /// image (one without table info).
+ //
+ /// NOTE: ownership is NOT transferred
+ ///
+ jpeg::input* get_jpeg_loader()
+ {
+ return m_jpeg_in.get();
+ }
+
+ virtual const std::vector<execute_tag*>& get_playlist(size_t
frame_number)
+ {
+ return m_playlist[frame_number];
+ }
+
+ virtual const std::vector<execute_tag*>* get_init_actions(size_t
frame_number)
+ {
+ assert(frame_number <= m_loading_frame);
+ //ensure_frame_loaded(frame_number);
+ return &m_init_action_list[frame_number];
+ }
+
+ /// Read (w/out playing) a Movie definition from an SWF file.
+ //
+ /// Note that the *full* SWF is read before
+ /// this function returns. We should change this
+ /// interface to both read and play a file instead.
+ ///
+ /// This function uses a private TagLoadersTable
+ /// to interpret specific tag types.
+ /// Currently the TagLoadersTable in use is the
+ /// gnash::s_tag_loaders global variable
+ ///
+ /// @param in the tu_file from which to read SWF
+ /// @param url the url associated with the input
+ /// @return false if SWF file could not be parsed
+ ///
+ bool read(tu_file *in, const std::string& url);
+
+ /// \brief
+ /// Ensure that frame number 'framenum' (1-based offset)
+ /// has been loaded (load on demand).
+ ///
+ bool ensure_frame_loaded(size_t framenum);
+
+ /// Read and parse all the SWF stream (blocking until load is finished)
+ void read_all_swf();
+
+ virtual void load_next_frame_chunk();
+
+ /// Fill up *fonts with fonts that we own.
+ void get_owned_fonts(std::vector<font*>* fonts);
+
+ /// Generate bitmaps for our fonts, if necessary.
+ void generate_font_bitmaps();
+
+ /// Dump our cached data into the given stream.
+ void output_cached_data(tu_file* out,
+ const cache_options& options);
+
+ /// \brief
+ /// Read in cached data and use it to prime our
+ /// loaded characters.
+ void input_cached_data(tu_file* in);
+
+ /// \brief
+ /// Create a playable movie_root instance from a def.
+ //
+ /// The _root reference of the newly created instance
+ /// will be set to a newly created sprite_instace (Help!)
+ ///
+ movie_interface* create_instance();
+
+ virtual const std::string& get_url() const { return _url; }
+
+
+};
+
+} // namespace gnash
+
+#endif // GNASH_MOVIE_DEF_IMPL_H
Index: server/parser/movie_definition.h
===================================================================
RCS file: server/parser/movie_definition.h
diff -N server/parser/movie_definition.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/movie_definition.h 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,269 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+
+
+/// \page movie SWF Movies
+///
+/// SWF Movies definitions are created by reading an SWF stream.
+/// Gnash doesn't play SWF Movie definitions, but instances.
+/// So you can play the same SWF file (Movie definiton) using
+/// multiple instances.
+///
+/// A Movie definition is defined by the gnash::movie_definition class.
+/// A Movie instance is defined by the gnash::movie_interface class.
+///
+/// A Movie instance exposes the ActionScript
+/// Object base interface (gnash::as_object),
+/// thus it can manage gnash::as_value members.
+///
+/// The implementation of SWF parsing for a Movie definition
+/// is found in gnash::movie_def_impl::read.
+/// Note that movie_definition is also used as a base class
+/// to sprite_definition, which is a sub-movie defined in an SWF
+/// file. This seems to be the only reason to have a
+/// movie_def_impl class, being the top-level definition of
+/// a movie (the one with a CharacterDictionary in it).
+///
+
+
+#ifndef GNASH_MOVIE_DEFINITION_H
+#define GNASH_MOVIE_DEFINITION_H
+
+#include "container.h"
+#include "button.h" // for mouse_button_state
+#include "timers.h" // for Timer
+#include "fontlib.h"
+#include "font.h"
+#include "jpeg.h"
+#include "tu_file.h"
+
+#include <string>
+#include <memory> // for auto_ptr
+
+namespace gnash
+{
+
+/// Client program's interface to the definition of a movie
+//
+/// (i.e. the shared constant source info).
+///
+struct movie_definition : public character_def
+{
+ virtual int get_version() const = 0;
+ virtual float get_width_pixels() const = 0;
+ virtual float get_height_pixels() const = 0;
+ virtual size_t get_frame_count() const = 0;
+ virtual float get_frame_rate() const = 0;
+
+ virtual size_t get_bytes_loaded() const = 0;
+ virtual size_t get_bytes_total() const = 0;
+
+ /// Create a playable movie instance from a def.
+ //
+ /// This calls add_ref() on the movie_interface internally.
+ /// Call drop_ref() on the movie_interface when you're done with it.
+ /// Or use smart_ptr<T> from base/smart_ptr.h if you want.
+ ///
+ virtual movie_interface* create_instance() = 0;
+
+ virtual void output_cached_data(tu_file* out, const cache_options&
options) = 0;
+ virtual void input_cached_data(tu_file* in) = 0;
+
+ /// \brief
+ /// Causes this movie def to generate texture-mapped
+ /// versions of all the fonts it owns.
+ //
+ /// This improves
+ /// speed and quality of text rendering. The
+ /// texture-map data is serialized in the
+ /// output/input_cached_data() calls, so you can
+ /// preprocess this if you load cached data.
+ ///
+ virtual void generate_font_bitmaps() = 0;
+
+ //
+ // (optional) API to support gnash::create_movie_no_recurse().
+ //
+
+ /// \brief
+ /// Call visit_imported_movies() to retrieve a list of
+ /// names of movies imported into this movie.
+ //
+ /// visitor->visit() will be called back with the name
+ /// of each imported movie.
+ struct import_visitor
+ {
+ virtual ~import_visitor() {}
+ virtual void visit(const char* imported_movie_filename) = 0;
+ };
+ virtual void visit_imported_movies(import_visitor* visitor) = 0;
+
+ /// Call this to resolve an import of the given movie.
+ /// Replaces the dummy placeholder with the real
+ /// movie_definition* given.
+ virtual void resolve_import(const char* name, movie_definition* def)
= 0;
+
+ //
+ // (optional) API to support host-driven creation of textures.
+ //
+ // Create the movie using gnash::create_movie_no_recurse(...,
DO_NOT_LOAD_BITMAPS),
+ // and then initialize each bitmap info via get_bitmap_info_count(),
get_bitmap_info(),
+ // and bitmap_info::init_*_image() or your own subclassed API.
+ //
+ // E.g.:
+ //
+ // // During preprocessing:
+ // // This will create bitmap_info's using the rgba, rgb, alpha
contructors.
+ // my_def = gnash::create_movie_no_recurse("myfile.swf",
DO_LOAD_BITMAPS);
+ // int ct = my_def->get_bitmap_info_count();
+ // for (int i = 0; i < ct; i++)
+ // {
+ // my_bitmap_info_subclass* bi = NULL;
+ // my_def->get_bitmap_info(i, (bitmap_info**) &bi);
+ //
my_precomputed_textures.push_back(bi->m_my_internal_texture_reference);
+ // }
+ // // Save out my internal data.
+ // my_precomputed_textures->write_into_some_cache_stream(...);
+ //
+ // // Later, during run-time loading:
+ // my_precomputed_textures->read_from_some_cache_stream(...);
+ // // This will create blank bitmap_info's.
+ // my_def = gnash::create_movie_no_recurse("myfile.swf",
DO_NOT_LOAD_BITMAPS);
+ //
+ // // Push cached texture info into the movie's bitmap_info structs.
+ // int ct = my_def->get_bitmap_info_count();
+ // for (int i = 0; i < ct; i++)
+ // {
+ // my_bitmap_info_subclass* bi = (my_bitmap_info_subclass*)
my_def->get_bitmap_info(i);
+ // bi->set_internal_texture_reference(my_precomputed_textures[i]);
+ // }
+ virtual int get_bitmap_info_count() const = 0;
+ virtual bitmap_info* get_bitmap_info(int i) const = 0;
+
+ // From movie_definition_sub
+
+ virtual const std::vector<execute_tag*>& get_playlist(size_t
frame_number) = 0;
+ virtual const std::vector<execute_tag*>* get_init_actions(size_t
frame_number) = 0;
+ virtual smart_ptr<resource> get_exported_resource(const tu_string&
symbol) = 0;
+
+
+ /// \brief
+ /// Get a character from the dictionary.
+ ///
+ /// Note that only top-level movies (those belonging to a single
+ /// SWF stream) have a characters dictionary, thus our
+ /// movie_def_impl. The other derived class, sprite_definition
+ /// will seek for characters in it's base movie_def_impl.
+ ///
+ virtual character_def* get_character_def(int id) = 0;
+
+ virtual bool get_labeled_frame(const char* label, size_t* frame_number)
= 0;
+
+ //
+ // For use during creation.
+ //
+
+ /// Returns 1 based index. Ex: if 1 then 1st frame as been fully loaded
+ virtual size_t get_loading_frame() const = 0;
+
+ virtual void add_character(int id, character_def* ch) = 0;
+
+ virtual void add_font(int id, font* ch) = 0;
+
+ virtual font* get_font(int id) = 0;
+
+ virtual void add_execute_tag(execute_tag* c) = 0;
+
+ // sprite_id was useless
+ //virtual void add_init_action(int sprite_id, execute_tag* c) = 0;
+ virtual void add_init_action(execute_tag* c) = 0;
+
+ virtual void add_frame_name(const char* name) = 0;
+
+ virtual void set_jpeg_loader(std::auto_ptr<jpeg::input> j_in) = 0;
+
+ virtual jpeg::input* get_jpeg_loader() = 0;
+
+ virtual bitmap_character_def* get_bitmap_character(int character_id)=0;
+
+ virtual void add_bitmap_character(int character_id,
+ bitmap_character_def* ch) = 0;
+
+ virtual sound_sample* get_sound_sample(int character_id) = 0;
+
+ virtual void add_sound_sample(int character_id, sound_sample* sam) = 0;
+
+ virtual void set_loading_sound_stream_id(int id) = 0;
+
+ virtual int get_loading_sound_stream_id() = 0;
+
+
+ virtual void export_resource(const tu_string& symbol,
+ resource* res) = 0;
+
+ virtual void add_import(const char* source_url, int id,
+ const char* symbol_name) = 0;
+
+ virtual void add_bitmap_info(bitmap_info* ch) = 0;
+
+ // ...
+
+ virtual create_bitmaps_flag get_create_bitmaps() const = 0;
+ virtual create_font_shapes_flag get_create_font_shapes() const = 0;
+
+ /// \brief
+ /// Return the URL of the SWF stream this definition has been read
+ /// from.
+ virtual const std::string& get_url() const = 0;
+
+ /// \brief
+ /// Ensure that frame number 'framenum' (1-based offset)
+ /// has been loaded (load on demand).
+ //
+ /// @return false on error (like not enough frames available).
+ ///
+ virtual bool ensure_frame_loaded(size_t framenum) = 0;
+
+ /// \brief
+ /// Load next chunk of this movie/sprite frames if available.
+ ///
+ virtual void load_next_frame_chunk() = 0;
+};
+
+} // namespace gnash
+
+#endif // GNASH_MOVIE_DEFINITION_H
Index: server/parser/shape_character_def.cpp
===================================================================
RCS file: server/parser/shape_character_def.cpp
diff -N server/parser/shape_character_def.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/shape_character_def.cpp 24 Aug 2006 00:57:20 -0000
1.1
@@ -0,0 +1,718 @@
+// shape.cpp -- Thatcher Ulrich <address@hidden> 2003
+
+// This source code has been donated to the Public Domain. Do
+// whatever you want with it.
+
+// Quadratic bezier outline shapes, the basis for most SWF rendering.
+
+
+#include "shape_character_def.h"
+#include "shape.h" // for mesh_set
+
+#include "impl.h"
+#include "log.h"
+#include "render.h"
+#include "stream.h"
+#include "tesselate.h"
+#include "movie_definition.h" // TODO: check if really needed
+//#include "bitmap_character_def.h"
+#include "sprite_instance.h"
+
+#include "tu_file.h"
+
+#include <float.h>
+
+
+#define DEBUG_DISPLAY_SHAPE_PATHS
+#ifdef DEBUG_DISPLAY_SHAPE_PATHS
+// For debugging only!
+bool gnash_debug_show_paths = false;
+#endif // DEBUG_DISPLAY_SHAPE_PATHS
+
+
+namespace gnash {
+
+static float s_curve_max_pixel_error = 1.0f;
+
+
+//
+// helper functions.
+//
+
+void set_curve_max_pixel_error(float pixel_error)
+{
+ s_curve_max_pixel_error = fclamp(pixel_error, 1e-6f, 1e6f);
+}
+
+float get_curve_max_pixel_error()
+{
+ return s_curve_max_pixel_error;
+}
+
+
+// Read fill styles, and push them onto the given style array.
+static void
+read_fill_styles(std::vector<fill_style>& styles, stream* in,
+ int tag_type, movie_definition* m)
+{
+ //assert(styles);
+
+ // Get the count.
+ int fill_style_count = in->read_u8();
+ if (tag_type > 2) {
+ if (fill_style_count == 0xFF)
+ {
+ fill_style_count = in->read_u16();
+ }
+ }
+
+ IF_VERBOSE_PARSE (
+ log_parse(" read_fill_styles: count = %d", fill_style_count);
+ );
+
+ // Read the styles.
+ for (int i = 0; i < fill_style_count; i++) {
+ styles.resize(styles.size() + 1);
+ //styles[styles.size() - 1].read(in, tag_type, m);
+ styles.back().read(in, tag_type, m);
+ }
+}
+
+
+static void
+read_line_styles(std::vector<line_style>& styles, stream* in, int tag_type)
+ // Read line styles and push them onto the back of the given array.
+{
+ // Get the count.
+ int line_style_count = in->read_u8();
+
+ IF_VERBOSE_PARSE
+ (
+ log_parse(" read_line_styles: count = %d", line_style_count);
+ );
+
+ // @@ does the 0xFF flag apply to all tag types?
+ // if (tag_type > 2)
+ // {
+ if (line_style_count == 0xFF) {
+ line_style_count = in->read_u16();
+ IF_VERBOSE_PARSE
+ (
+ log_parse(" read_line_styles: count2 = %d", line_style_count);
+ );
+ }
+ // }
+
+ // Read the styles.
+ for (int i = 0; i < line_style_count; i++) {
+ styles.resize(styles.size() + 1);
+ //styles[styles.size() - 1].read(in, tag_type);
+ styles.back().read(in, tag_type);
+ }
+}
+
+
+shape_character_def::shape_character_def()
+{
+}
+
+
+shape_character_def::~shape_character_def()
+{
+ // Free our mesh_sets.
+ for (unsigned int i = 0; i < m_cached_meshes.size(); i++) {
+ delete m_cached_meshes[i];
+ }
+}
+
+
+void
+shape_character_def::read(stream* in, int tag_type, bool with_style,
+ movie_definition* m)
+{
+ if (with_style) {
+ m_bound.read(in);
+ read_fill_styles(m_fill_styles, in, tag_type, m);
+ read_line_styles(m_line_styles, in, tag_type);
+ }
+
+ int num_fill_bits = in->read_uint(4);
+ int num_line_bits = in->read_uint(4);
+
+ IF_VERBOSE_PARSE
+ (
+ log_parse(" shape_character_def read: nfillbits = %d, nlinebits = %d",
num_fill_bits, num_line_bits);
+ );
+
+ // These are state variables that keep the
+ // current position & style of the shape
+ // outline, and vary as we read the edge data.
+ //
+ // At the moment we just store each edge with
+ // the full necessary info to render it, which
+ // is simple but not optimally efficient.
+ int fill_base = 0;
+ int line_base = 0;
+ float x = 0, y = 0;
+ path current_path;
+
+#define SHAPE_LOG 0
+ // SHAPERECORDS
+ for (;;) {
+ int type_flag = in->read_uint(1);
+ if (type_flag == 0) {
+ // Parse the record.
+ int flags = in->read_uint(5);
+ if (flags == 0) {
+ // End of shape records.
+
+ // Store the current path if any.
+ if (! current_path.is_empty())
+ {
+ m_paths.push_back(current_path);
+ current_path.m_edges.resize(0);
+ }
+
+ break;
+ }
+ if (flags & 0x01) {
+ // move_to = 1;
+
+ // Store the current path if any, and prepare a fresh one.
+ if (! current_path.is_empty()) {
+ m_paths.push_back(current_path);
+ current_path.m_edges.resize(0);
+ }
+
+ int num_move_bits = in->read_uint(5);
+ int move_x = in->read_sint(num_move_bits);
+ int move_y = in->read_sint(num_move_bits);
+
+ x = (float) move_x;
+ y = (float) move_y;
+
+ // Set the beginning of the path.
+ current_path.m_ax = x;
+ current_path.m_ay = y;
+
+ IF_VERBOSE_PARSE
+ (
+ if (SHAPE_LOG)
+ log_parse(" shape_character read: moveto %4g %4g", x, y);
+ );
+ }
+ if ((flags & 0x02) && num_fill_bits > 0) {
+ // fill_style_0_change = 1;
+ if (! current_path.is_empty()) {
+ m_paths.push_back(current_path);
+ current_path.m_edges.resize(0);
+ current_path.m_ax = x;
+ current_path.m_ay = y;
+ }
+ int style = in->read_uint(num_fill_bits);
+ if (style > 0) {
+ style += fill_base;
+ }
+ current_path.m_fill0 = style;
+ IF_VERBOSE_PARSE
+ (
+ if (SHAPE_LOG) {
+ log_parse(" shape_character read: fill0 = %d",
current_path.m_fill0);
+ }
+ );
+
+ }
+ if ((flags & 0x04) && num_fill_bits > 0) {
+ // fill_style_1_change = 1;
+ if (! current_path.is_empty()) {
+ m_paths.push_back(current_path);
+ current_path.m_edges.resize(0);
+ current_path.m_ax = x;
+ current_path.m_ay = y;
+ }
+ int style = in->read_uint(num_fill_bits);
+ if (style > 0) {
+ style += fill_base;
+ }
+ current_path.m_fill1 = style;
+ IF_VERBOSE_PARSE (
+ if (SHAPE_LOG) {
+ log_parse(" shape_character read: fill1 = %d",
current_path.m_fill1);
+ }
+ );
+ }
+ if ((flags & 0x08) && num_line_bits > 0) {
+ // line_style_change = 1;
+ if (! current_path.is_empty()) {
+ m_paths.push_back(current_path);
+ current_path.m_edges.resize(0);
+ current_path.m_ax = x;
+ current_path.m_ay = y;
+ }
+ int style = in->read_uint(num_line_bits);
+ if (style > 0) {
+ style += line_base;
+ }
+ current_path.m_line = style;
+ IF_VERBOSE_PARSE (
+ if (SHAPE_LOG)
+ {
+ log_parse(" shape_character_read: line = %d",
current_path.m_line);
+ }
+ );
+ }
+ if (flags & 0x10) {
+ if (tag_type == 2) {
+ tag_type+=20;
+ }
+ assert(tag_type >= 22);
+
+ IF_VERBOSE_PARSE (
+ log_parse(" shape_character read: more fill styles");
+ );
+
+ // Store the current path if any.
+ if (! current_path.is_empty()) {
+ m_paths.push_back(current_path);
+ current_path.m_edges.resize(0);
+
+ // Clear styles.
+ current_path.m_fill0 = -1;
+ current_path.m_fill1 = -1;
+ current_path.m_line = -1;
+ }
+ // Tack on an empty path signalling a new shape.
+ // @@ need better understanding of whether this is correct??!?!!
+ // @@ i.e., we should just start a whole new shape here, right?
+ m_paths.push_back(path());
+ m_paths.back().m_new_shape = true;
+
+ fill_base = m_fill_styles.size();
+ line_base = m_line_styles.size();
+ read_fill_styles(m_fill_styles, in, tag_type, m);
+ read_line_styles(m_line_styles, in, tag_type);
+ num_fill_bits = in->read_uint(4);
+ num_line_bits = in->read_uint(4);
+ }
+ } else {
+ // EDGERECORD
+ int edge_flag = in->read_uint(1);
+ if (edge_flag == 0) {
+ // curved edge
+ int num_bits = 2 + in->read_uint(4);
+ float cx = x + in->read_sint(num_bits);
+ float cy = y + in->read_sint(num_bits);
+ float ax = cx + in->read_sint(num_bits);
+ float ay = cy + in->read_sint(num_bits);
+
+ IF_VERBOSE_PARSE (
+ if (SHAPE_LOG)
+ {
+ log_parse(" shape_character read: curved edge = %4g %4g
- %4g %4g - %4g %4g", x, y, cx, cy, ax, ay);
+ }
+ );
+
+ current_path.m_edges.push_back(edge(cx, cy, ax, ay));
+
+ x = ax;
+ y = ay;
+ } else {
+ // straight edge
+ int num_bits = 2 + in->read_uint(4);
+ int line_flag = in->read_uint(1);
+ float dx = 0, dy = 0;
+ if (line_flag) {
+ // General line.
+ dx = (float) in->read_sint(num_bits);
+ dy = (float) in->read_sint(num_bits);
+ } else {
+ int vert_flag = in->read_uint(1);
+ if (vert_flag == 0) {
+ // Horizontal line.
+ dx = (float) in->read_sint(num_bits);
+ } else {
+ // Vertical line.
+ dy = (float) in->read_sint(num_bits);
+ }
+ }
+
+ IF_VERBOSE_PARSE (
+ if (SHAPE_LOG)
+ {
+ log_parse(" shape_character_read: straight edge = %4g %4g
- %4g %4g", x, y, x + dx, y + dy);
+ }
+ );
+
+ current_path.m_edges.push_back(edge(x + dx, y + dy, x + dx, y +
dy));
+
+ x += dx;
+ y += dy;
+ }
+ }
+ }
+}
+
+
+void shape_character_def::display(character* inst)
+ // Draw the shape using our own inherent styles.
+{
+// GNASH_REPORT_FUNCTION;
+
+ matrix mat = inst->get_world_matrix();
+ cxform cx = inst->get_world_cxform();
+
+ float pixel_scale = inst->get_parent()->get_pixel_scale();
+ display(mat, cx, pixel_scale, m_fill_styles, m_line_styles);
+}
+
+
+#ifdef DEBUG_DISPLAY_SHAPE_PATHS
+
+#include "ogl.h"
+
+
+static void point_normalize(point* p)
+{
+ float mag2 = p->m_x * p->m_x + p->m_y * p->m_y;
+ if (mag2 < 1e-9f) {
+ // Very short vector.
+ // @@ log error
+
+ // Arbitrary unit vector.
+ p->m_x = 1;
+ p->m_y = 0;
+ }
+
+ float inv_mag = 1.0f / sqrtf(mag2);
+ p->m_x *= inv_mag;
+ p->m_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.m_x;
+ float y = p.m_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 matrix& 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++) {
+// if (i > 0) break;//xxxxxxxx
+ const path& p = paths[i];
+
+ if (p.m_fill0 == 0 && p.m_fill1 == 0) {
+ continue;
+ }
+
+ gnash::render::set_matrix(mat);
+
+ // Color the line according to which side has
+ // fills.
+ if (p.m_fill0 == 0) glColor4f(1, 0, 0, 0.5);
+ else if (p.m_fill1 == 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.m_ax, p.m_ay));
+ glVertex2f(pt.m_x, pt.m_y);
+
+ for (unsigned int j = 0; j < p.m_edges.size(); j++) {
+ mat.transform(&pt, point(p.m_edges[j].m_cx, p.m_edges[j].m_cy));
+ glVertex2f(pt.m_x, pt.m_y);
+ mat.transform(&pt, point(p.m_edges[j].m_ax, p.m_edges[j].m_ay));
+ glVertex2f(pt.m_x, pt.m_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].m_cx, p.m_edges[j].m_cy));
+ mat.transform(&p1, point(p.m_edges[j].m_ax, p.m_edges[j].m_ay));
+ dir = point(p1.m_x - p0.m_x, p1.m_y - p0.m_y);
+ point_normalize(&dir);
+ right = point(-dir.m_y, dir.m_x); // perpendicular
+
+ const float ARROW_MAG = 60.f; // TWIPS?
+ if (p.m_fill0 != 0)
+ {
+ glColor4f(0, 1, 0, 0.5);
+ glVertex2f(p0.m_x,
+ p0.m_y);
+ glVertex2f(p0.m_x - dir.m_x * ARROW_MAG - right.m_x *
ARROW_MAG,
+ p0.m_y - dir.m_y * ARROW_MAG - right.m_y *
ARROW_MAG);
+
+ show_fill_number(point(p0.m_x - right.m_x * ARROW_MAG *
4,
+ p0.m_y - right.m_y * ARROW_MAG *
4),
+ p.m_fill0);
+ }
+ if (p.m_fill1 != 0)
+ {
+ glColor4f(1, 0, 0, 0.5);
+ glVertex2f(p0.m_x,
+ p0.m_y);
+ glVertex2f(p0.m_x - dir.m_x * ARROW_MAG + right.m_x *
ARROW_MAG,
+ p0.m_y - dir.m_y * ARROW_MAG + right.m_y *
ARROW_MAG);
+
+ show_fill_number(point(p0.m_x + right.m_x * ARROW_MAG *
4,
+ p0.m_y + right.m_y * ARROW_MAG *
4),
+ p.m_fill1);
+ }
+ }}
+ glEnd();
+
+ glPopMatrix();
+ }
+}
+#endif // DEBUG_DISPLAY_SHAPE_PATHS
+
+
+void shape_character_def::display(
+ const matrix& mat,
+ const cxform& cx,
+ float pixel_scale,
+ const std::vector<fill_style>& fill_styles,
+ const std::vector<line_style>& line_styles) const
+ // Display our shape. Use the fill_styles arg to
+ // override our default set of fill styles (e.g. when
+ // rendering text).
+{
+// GNASH_REPORT_FUNCTION;
+
+ // Compute the error tolerance in object-space.
+ float max_scale = mat.get_max_scale();
+ if (fabsf(max_scale) < 1e-6f) {
+ // Scale is essentially zero.
+ return;
+ }
+
+ float object_space_max_error = 20.0f / max_scale / pixel_scale *
s_curve_max_pixel_error;
+
+#ifdef DEBUG_DISPLAY_SHAPE_PATHS
+ // Render a debug view of shape path outlines, instead
+ // of the tesselated shapes themselves.
+ if (gnash_debug_show_paths) {
+ debug_display_shape_paths(mat, object_space_max_error, m_paths,
fill_styles, line_styles);
+
+ return;
+ }
+#endif // DEBUG_DISPLAY_SHAPE_PATHS
+
+ // See if we have an acceptable mesh available; if so then render with it.
+ for (unsigned int i = 0, n = m_cached_meshes.size(); i < n; i++) {
+ const mesh_set* candidate = m_cached_meshes[i];
+
+ if (object_space_max_error > candidate->get_error_tolerance() * 3.0f)
+ {
+ // Mesh is too high-res; the remaining meshes are higher res,
+ // so stop searching and build an appropriately scaled mesh.
+ break;
+ }
+
+ if (object_space_max_error > candidate->get_error_tolerance()) {
+ // Do it.
+ candidate->display(mat, cx, fill_styles, line_styles);
+ return;
+ }
+ }
+
+ // Construct a new mesh to handle this error tolerance.
+ mesh_set* m = new mesh_set(this, object_space_max_error * 0.75f);
+ m_cached_meshes.push_back(m);
+ m->display(mat, cx, fill_styles, line_styles);
+
+ sort_and_clean_meshes();
+}
+
+
+static int sort_by_decreasing_error(const void* A, const void* B)
+{
+ const mesh_set* a = *(const mesh_set* const *) A;
+ const mesh_set* b = *(const mesh_set* const *) B;
+
+ if (a->get_error_tolerance() < b->get_error_tolerance()) {
+ return 1;
+ } else if (a->get_error_tolerance() > b->get_error_tolerance()) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+void shape_character_def::sort_and_clean_meshes() const
+ // Maintain cached meshes. Clean out mesh_sets that haven't
+ // been used recently, and make sure they're sorted from high
+ // error to low error.
+{
+ // Re-sort.
+ if (m_cached_meshes.size() > 0) {
+ qsort(
+ &m_cached_meshes[0],
+ m_cached_meshes.size(),
+ sizeof(m_cached_meshes[0]),
+ sort_by_decreasing_error);
+
+ // Check to make sure the sort worked as intended.
+#ifndef NDEBUG
+ for (unsigned int i = 0, n = m_cached_meshes.size() - 1; i < n; i++) {
+ const mesh_set* a = m_cached_meshes[i];
+ const mesh_set* b = m_cached_meshes[i + 1];
+
+ assert(a->get_error_tolerance() > b->get_error_tolerance());
+ }
+#endif // not NDEBUG
+ }
+}
+
+
+void shape_character_def::tesselate(float error_tolerance,
tesselate::trapezoid_accepter* accepter) const
+ // Push our shape data through the tesselator.
+{
+ tesselate::begin_shape(accepter, error_tolerance);
+ for (unsigned int i = 0; i < m_paths.size(); i++) {
+ if (m_paths[i].m_new_shape == true) {
+ // Hm; should handle separate sub-shapes in a less lame way.
+ tesselate::end_shape();
+ tesselate::begin_shape(accepter, error_tolerance);
+ } else {
+ m_paths[i].tesselate();
+ }
+ }
+ tesselate::end_shape();
+}
+
+
+bool shape_character_def::point_test_local(float x, float y)
+ // Return true if the specified point is on the interior of our shape.
+ // Incoming coords are local coords.
+{
+ if (m_bound.point_test(x, y) == false) {
+ // Early out.
+ return false;
+ }
+
+ // Try each of the paths.
+ for (unsigned int i = 0; i < m_paths.size(); i++) {
+ if (m_paths[i].point_test(x, y))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+float shape_character_def::get_height_local()
+{
+ return m_bound.height();
+}
+
+float shape_character_def::get_width_local()
+{
+ return m_bound.width();
+}
+
+
+void shape_character_def::compute_bound(rect* r) const
+ // Find the bounds of this shape, and store them in
+ // the given rectangle.
+{
+ r->m_x_min = 1e10f;
+ r->m_y_min = 1e10f;
+ r->m_x_max = -1e10f;
+ r->m_y_max = -1e10f;
+
+ for (unsigned int i = 0; i < m_paths.size(); i++) {
+ const path& p = m_paths[i];
+ r->expand_to_point(p.m_ax, p.m_ay);
+ for (unsigned int j = 0; j < p.m_edges.size(); j++) {
+ r->expand_to_point(p.m_edges[j].m_ax, p.m_edges[j].m_ay);
+// r->expand_to_point(p.m_edges[j].m_cx,
p.m_edges[j].m_cy);
+ }
+ }
+}
+
+
+void shape_character_def::output_cached_data(tu_file* out, const
cache_options& /* options */)
+ // Dump our precomputed mesh data to the given stream.
+{
+ int n = m_cached_meshes.size();
+ out->write_le32(n);
+
+ for (int i = 0; i < n; i++) {
+ m_cached_meshes[i]->output_cached_data(out);
+ }
+}
+
+
+void shape_character_def::input_cached_data(tu_file* in)
+ // Initialize our mesh data from the given stream.
+{
+ int n = in->read_le32();
+
+ m_cached_meshes.resize(n);
+
+ for (int i = 0; i < n; i++) {
+ mesh_set* ms = new mesh_set();
+ ms->input_cached_data(in);
+ m_cached_meshes[i] = ms;
+ }
+}
+
+
+} // end namespace gnash
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/parser/shape_character_def.h
===================================================================
RCS file: server/parser/shape_character_def.h
diff -N server/parser/shape_character_def.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/shape_character_def.h 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,85 @@
+// shape.h -- Thatcher Ulrich <address@hidden> 2003
+
+// This source code has been donated to the Public Domain. Do
+// whatever you want with it.
+
+// Quadratic bezier outline shapes, the basis for most SWF rendering.
+
+
+#ifndef GNASH_SHAPE_CHARACTER_DEF_H
+#define GNASH_SHAPE_CHARACTER_DEF_H
+
+
+#include "styles.h"
+#include "character_def.h" // for inheritance of shape_character_def
+#include "tesselate.h"
+#include "shape.h" // for path
+
+
+namespace gnash {
+
+ /// \brief
+ /// Represents the outline of one or more shapes, along with
+ /// information on fill and line styles.
+ class shape_character_def : public character_def, public
tesselate::tesselating_shape
+ {
+ public:
+ shape_character_def();
+ virtual ~shape_character_def();
+
+ virtual void display(character* inst);
+ bool point_test_local(float x, float y);
+
+ float get_height_local();
+ float get_width_local();
+
+ void read(stream* in, int tag_type, bool with_style,
movie_definition* m);
+ void display(
+ const matrix& mat,
+ const cxform& cx,
+ float pixel_scale,
+ const std::vector<fill_style>& fill_styles,
+ const std::vector<line_style>& line_styles) const;
+ virtual void tesselate(float error_tolerance,
tesselate::trapezoid_accepter* accepter) const;
+ const rect& get_bound() const { return m_bound; }
+ void compute_bound(rect* r) const; // @@ what's the
difference between this and get_bound?
+
+ void output_cached_data(tu_file* out, const cache_options&
options);
+ void input_cached_data(tu_file* in);
+
+ const std::vector<fill_style>& get_fill_styles() const {
return m_fill_styles; }
+ const std::vector<line_style>& get_line_styles() const {
return m_line_styles; }
+ 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 */ }
+
+ protected:
+ friend class morph2_character_def;
+
+ // derived morph classes changes these
+ std::vector<fill_style> m_fill_styles;
+ std::vector<line_style> m_line_styles;
+ std::vector<path> m_paths;
+
+ private:
+ void sort_and_clean_meshes() const;
+
+ rect m_bound;
+
+ // Cached pre-tesselated meshes.
+ mutable std::vector<mesh_set*> m_cached_meshes;
+ };
+
+} // end namespace gnash
+
+
+#endif // GNASH_SHAPE_CHARACTER_DEF_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: server/parser/sprite_definition.cpp
===================================================================
RCS file: server/parser/sprite_definition.cpp
diff -N server/parser/sprite_definition.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/sprite_definition.cpp 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,181 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+// This needs to be included first for NetBSD systems or we get a weird
+// problem with pthread_t being defined too many times if we use any
+// STL containers.
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include "sprite_instance.h"
+#include "sprite_definition.h"
+#include "execute_tag.h" // for dtor visibility
+
+#include <vector>
+#include <string>
+#include <cassert>
+
+using namespace std;
+
+namespace gnash {
+
+character*
+sprite_definition::create_character_instance(character* parent,
+ int id)
+{
+ sprite_instance* si = new sprite_instance(this,
+ parent->get_root(), parent, id);
+ return si;
+}
+
+sprite_definition::~sprite_definition()
+{
+ // Release our playlist data.
+ for (int i = 0, n = m_playlist.size(); i < n; i++)
+ {
+ for (int j = 0, m = m_playlist[i].size(); j < m; j++)
+ {
+ delete m_playlist[i][j];
+ }
+ }
+}
+
+/*private*/
+// only called from constructors
+void
+sprite_definition::read(stream* in)
+{
+ int tag_end = in->get_tag_end_position();
+
+ m_frame_count = in->read_u16();
+
+ // ALEX: some SWF files have been seen that have 0-frame sprites.
+ // The Macromedia player behaves as if they have 1 frame.
+ if (m_frame_count < 1)
+ {
+ m_frame_count = 1;
+ }
+
+ // need a playlist for each frame
+ m_playlist.resize(m_frame_count);
+
+ IF_VERBOSE_PARSE (
+ log_parse(" frames = %u", m_frame_count);
+ );
+
+ m_loading_frame = 0;
+
+ while ((uint32_t) in->get_position() < (uint32_t) tag_end)
+ {
+ SWF::tag_type tag_type = in->open_tag();
+
+ SWF::TagLoadersTable::loader_function lf = NULL;
+
+ if (tag_type == SWF::DEFINESPRITE)
+ {
+ log_error("DefineSprite tag inside sprite "
+ "definition - Malformed SWF!");
+ }
+
+ if (tag_type == SWF::SHOWFRAME)
+ {
+ // show frame tag -- advance to the next frame.
+ IF_VERBOSE_PARSE (
+ log_parse(" show_frame (sprite)");
+ );
+ m_loading_frame++;
+ }
+ else if (_tag_loaders.get(tag_type, &lf))
+ {
+ // call the tag loader. The tag loader should add
+ // characters or tags to the movie data structure.
+ (*lf)(in, tag_type, this);
+ }
+ else
+ {
+ // no tag loader for this tag type.
+ log_error("*** no tag loader for type %d (sprite)",
+ tag_type);
+ }
+
+ in->close_tag();
+ }
+
+ IF_VERBOSE_PARSE (
+ log_parse(" -- sprite END --");
+ );
+}
+
+/*virtual*/
+void
+sprite_definition::add_frame_name(const char* name)
+{
+ assert((int)m_loading_frame >= 0 && m_loading_frame < m_frame_count);
+
+ tu_string n = name;
+ size_t currently_assigned = 0;
+ if (m_named_frames.get(n, ¤tly_assigned) == true)
+ {
+ log_error("add_frame_name(%d, '%s') -- frame name "
+ "already assigned to frame %u; overriding\n",
+ m_loading_frame,
+ name, currently_assigned);
+ }
+
+ // stores 0-based frame #
+ m_named_frames[n] = m_loading_frame;
+}
+
+sprite_definition::sprite_definition(movie_definition* m, stream* in)
+ :
+ _tag_loaders(s_tag_loaders), // FIXME: use a class-static
TagLoadersTable for sprite_definition
+ m_movie_def(m),
+ m_frame_count(0),
+ m_loading_frame(0)
+{
+ assert(m_movie_def);
+ read(in);
+}
+
+
+
+} // namespace gnash
Index: server/parser/sprite_definition.h
===================================================================
RCS file: server/parser/sprite_definition.h
diff -N server/parser/sprite_definition.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/sprite_definition.h 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,369 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+
+#ifndef GNASH_SPRITE_DEFINITION_H
+#define GNASH_SPRITE_DEFINITION_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <vector>
+
+#include "movie_definition.h"
+#include "stream.h"
+#include "log.h"
+
+namespace gnash
+{
+
+
+/// \brief
+/// Holds the immutable data for a sprite, as read from
+/// as SWF stream.
+/// @@ should *not* derive from movie_definition, probably!
+///
+class sprite_definition : public movie_definition
+{
+
+public:
+
+ /// \brief
+ /// Read the sprite info from input stream.
+ //
+ /// A sprite definition consists of a series control tags.
+ ///
+ /// @param m
+ /// the Top-Level movie_definition this sprite is read
+ /// from (not a sprite_definition!)
+ ///
+ /// @param in
+ /// The stream associated with the sprite. It is assumed
+ /// to be already positioned right before the frame count
+ ///
+ sprite_definition(movie_definition* m, stream* in);
+
+ /// Destructor, releases playlist data
+ ~sprite_definition();
+
+private:
+
+ void read(stream* in);
+
+ /// Tags loader table.
+ //
+ /// TODO: make it a static member, specific to sprite_definition
+ SWF::TagLoadersTable& _tag_loaders;
+
+ /// Top-level movie definition
+ /// (the definition read from SWF stream)
+ movie_definition* m_movie_def;
+
+ /// movie control events for each frame.
+ std::vector<std::vector<execute_tag*> > m_playlist;
+
+ // stores 0-based frame #'s
+ stringi_hash<size_t> m_named_frames;
+
+ size_t m_frame_count;
+
+ size_t m_loading_frame;
+
+ // overloads from movie_definition
+ virtual float get_width_pixels() const { return 1; }
+ virtual float get_height_pixels() const { return 1; }
+
+ virtual size_t get_frame_count() const
+ {
+ return m_frame_count;
+ }
+
+ /// \brief
+ /// Return total bytes of the movie from which this sprite
+ /// has been read.
+ ///
+ virtual size_t get_bytes_total() const
+ {
+ return m_movie_def->get_bytes_total();
+ }
+
+ /// \brief
+ /// Return the number of bytes loaded from the stream of the
+ /// the movie from which this sprite is being read.
+ ///
+ virtual size_t get_bytes_loaded() const
+ {
+ return m_movie_def->get_bytes_loaded();
+ }
+
+ virtual float get_frame_rate() const { return
m_movie_def->get_frame_rate(); }
+
+ // Return number of frames loaded (of current sprite)
+ virtual size_t get_loading_frame() const { return m_loading_frame; }
+
+ virtual int get_version() const { return
m_movie_def->get_version(); }
+
+ virtual void add_font(int /*id*/, font* /*ch*/)
+ {
+ log_error("add_font tag appears in sprite tags! "
+ "Malformed SWF?\n");
+ }
+
+ virtual font* get_font(int id) { return m_movie_def->get_font(id); }
+
+ virtual void set_jpeg_loader(std::auto_ptr<jpeg::input> /*j_in*/)
+ {
+ assert(0);
+ }
+
+ virtual jpeg::input* get_jpeg_loader()
+ {
+ return NULL;
+ }
+
+ virtual bitmap_character_def* get_bitmap_character(int id)
+ {
+ return m_movie_def->get_bitmap_character(id);
+ }
+
+ virtual void add_bitmap_character(int /*id*/,
+ bitmap_character_def* /*ch*/)
+ {
+ log_error("add_bc appears in sprite tags!"
+ " Malformed SWF?");
+ }
+
+ virtual sound_sample* get_sound_sample(int id)
+ {
+ return m_movie_def->get_sound_sample(id);
+ }
+
+ virtual void add_sound_sample(int /*id*/, sound_sample* /*sam*/)
+ {
+ log_error("add sam appears in sprite tags!"
+ " Malformed SWF?");
+ }
+
+ virtual void set_loading_sound_stream_id(int id) {
+ return m_movie_def->set_loading_sound_stream_id(id);
+ }
+
+ virtual int get_loading_sound_stream_id() {
+ return m_movie_def->get_loading_sound_stream_id();
+ }
+
+
+ // @@ would be nicer to not inherit these...
+ virtual create_bitmaps_flag get_create_bitmaps() const
+ { assert(0); return DO_LOAD_BITMAPS; }
+ virtual create_font_shapes_flag get_create_font_shapes() const
+ { assert(0); return DO_LOAD_FONT_SHAPES; }
+ virtual int get_bitmap_info_count() const
+ { assert(0); return 0; }
+ virtual bitmap_info* get_bitmap_info(int /*i*/) const
+ { assert(0); return NULL; }
+ virtual void add_bitmap_info(bitmap_info* /*bi*/)
+ { assert(0); }
+
+ virtual void export_resource(const tu_string& /*symbol*/,
+ resource* /*res*/)
+ {
+ log_error("can't export from sprite! Malformed SWF?");
+ }
+
+ virtual smart_ptr<resource> get_exported_resource(const tu_string& sym)
+ {
+ return m_movie_def->get_exported_resource(sym);
+ }
+
+ virtual void add_import(const char* /*source_url*/, int /*id*/,
+ const char* /*symbol*/)
+ {
+ assert(0);
+ }
+
+ virtual void visit_imported_movies(import_visitor* /*v*/)
+ {
+ assert(0);
+ }
+
+ virtual void resolve_import(const char* /*source_url*/,
+ movie_definition* /*d*/)
+ {
+ assert(0);
+ }
+
+
+ /// \brief
+ /// Get a character_def from this Sprite's parent
+ /// CharacterDictionary. NOTE that calling this
+ /// method on the leaf Sprite of a movie_definition
+ /// hierarchy will result in a recursive scan of
+ /// all parents until the top-level movie_definition
+ /// (movie_def_impl) is found.
+ ///
+ virtual character_def* get_character_def(int id)
+ {
+ return m_movie_def->get_character_def(id);
+ }
+
+ /// Calls to this function should only be made when
+ /// an invalid SWF is being read, as it would mean
+ /// that a Definition tag is been found as part of
+ /// a Sprite definition
+ ///
+ virtual void add_character(int /*id*/, character_def* /*ch*/)
+ {
+ log_error("add_character tag appears in sprite tags!"
+ " Maformed SWF?");
+ }
+
+
+ virtual void generate_font_bitmaps()
+ {
+ assert(0);
+ }
+
+ virtual void output_cached_data(tu_file* /*out*/,
+ const cache_options& /*options*/)
+ {
+ // Nothing to do.
+ return;
+ }
+
+ virtual void input_cached_data(tu_file* /*in*/)
+ {
+ // Nothing to do.
+ return;
+ }
+
+ virtual movie_interface* create_instance()
+ {
+ return NULL;
+ }
+
+ // Create a (mutable) instance of our definition. The
+ // instance is created to live (temporarily) on some level on
+ // the parent movie's display list.
+ //
+ // overloads from character_def
+ virtual character* create_character_instance(
+ character* parent, int id);
+
+
+ virtual void add_execute_tag(execute_tag* c)
+ {
+ m_playlist[m_loading_frame].push_back(c);
+ }
+
+ //virtual void add_init_action(int sprite_id, execute_tag* c)
+ virtual void add_init_action(execute_tag* /*c*/)
+ {
+ // Sprite def's should not have do_init_action tags in them! (@@
correct?)
+ log_error("sprite_definition::add_init_action called! Ignored.
(Malformed SWF?)\n");
+ }
+
+ /// \brief
+ /// Labels the frame currently being loaded with the
+ /// given name. A copy of the name string is made and
+ /// kept in this object.
+ ///
+ virtual void add_frame_name(const char* name);
+
+ /// Returns 0-based frame #
+ bool get_labeled_frame(const char* label, size_t* frame_number)
+ {
+ return m_named_frames.get(label, frame_number);
+ }
+
+ /// frame_number is 0-based
+ const std::vector<execute_tag*>& get_playlist(size_t frame_number)
+ {
+ return m_playlist[frame_number];
+ }
+
+ // Sprites do not have init actions in their
+ // playlists! Only the root movie
+ // (movie_def_impl) does (@@ correct?)
+ virtual const std::vector<execute_tag*>* get_init_actions(size_t
/*frame_number*/)
+ {
+ return NULL;
+ }
+
+ virtual const std::string& get_url() const
+ {
+ return m_movie_def->get_url();
+ }
+
+ /// \brief
+ /// Ensure framenum frames of this sprite
+ /// have been loaded.
+ ///
+ virtual bool ensure_frame_loaded(size_t framenum)
+ {
+ // TODO: return false on timeout
+ while ( m_loading_frame < framenum )
+ {
+ log_msg("sprite_definition: "
+ "loading of frame %u requested "
+ "(we are at %u/%u)",
+ framenum, m_loading_frame, m_frame_count);
+ // Could this ever happen ?
+ assert(0);
+ }
+ return true;
+ }
+
+ virtual void load_next_frame_chunk()
+ {
+ /// We load full sprite definitions at once, so
+ /// this function is a no-op.
+ }
+
+ /// Return the top-level movie definition
+ /// (the definition read from SWF stream)
+ movie_definition* get_movie_definition() {
+ return m_movie_def;
+ }
+
+
+};
+
+
+} // end of namespace gnash
+
+#endif // GNASH_SPRITE_H
Index: server/parser/text_character_def.h
===================================================================
RCS file: server/parser/text_character_def.h
diff -N server/parser/text_character_def.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/text_character_def.h 24 Aug 2006 00:57:20 -0000 1.1
@@ -0,0 +1,129 @@
+//
+// Copyright (C) 2005, 2006 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 2 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
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
+//
+
+// Code for the text tags.
+
+
+#ifndef GNASH_PARSER_TEXT_CHARACTER_DEF_H
+#define GNASH_PARSER_TEXT_CHARACTER_DEF_H
+
+#include "textformat.h" // maybe we should include it here
+#include "styles.h"
+
+namespace gnash {
+
+// Forward declarations
+struct text_character_def;
+struct text_glyph_record;
+
+// Helper struct.
+// @@ text_character_def friend ?
+struct text_style
+{
+ int m_font_id;
+ mutable const font* m_font;
+ rgba m_color;
+ float m_x_offset;
+ float m_y_offset;
+ float m_text_height;
+ bool m_has_x_offset;
+ bool m_has_y_offset;
+
+ text_style()
+ :
+ m_font_id(-1),
+ m_font(NULL),
+ m_x_offset(0),
+ m_y_offset(0),
+ m_text_height(1.0f),
+ m_has_x_offset(false),
+ m_has_y_offset(false)
+ {
+ }
+
+ void resolve_font(movie_definition* root_def) const;
+};
+
+
+// Helper struct.
+// @@ text_character_def friend ?
+struct text_glyph_record
+{
+ struct glyph_entry
+ {
+ int m_glyph_index;
+ float m_glyph_advance;
+ };
+ text_style m_style;
+ std::vector<glyph_entry> m_glyphs;
+
+ void read(stream* in, int glyph_count,
+ int glyph_bits, int advance_bits);
+
+};
+
+/// Text character
+//
+/// This is either read from SWF stream
+/// or (hopefully) created with scripting
+///
+struct text_character_def : public character_def
+{
+ movie_definition* m_root_def;
+ rect m_rect;
+ matrix m_matrix;
+ std::vector<text_glyph_record> m_text_glyph_records;
+
+ text_character_def(movie_definition* root_def)
+ :
+ m_root_def(root_def)
+ {
+ assert(m_root_def);
+ }
+
+ void read(stream* in, int tag_type, movie_definition* m);
+
+ /// Draw the string.
+ void display(character* inst);
+
+};
+
+
+} // namespace gnash
+
+#endif // GNASH_PARSER_TEXT_CHARACTER_DEF_H
Index: server/MovieClip.cpp
===================================================================
RCS file: server/MovieClip.cpp
diff -N server/MovieClip.cpp
--- server/MovieClip.cpp 6 Aug 2006 02:00:54 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,89 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-#ifdef HAVE_PTHREADS
-#include <pthread.h>
-#endif
-
-#include <iostream>
-#include <string>
-
-#include "MovieClip.h"
-#include "tu_file.h"
-#include "zlib_adapter.h"
-//#include "stream.h"
-//#include "jpeg.h"
-//#include "fontlib.h"
-//#include "font.h"
-#include "log.h"
-//#include "Sprite.h"
-//#include "sprite_instance.h"
-#include "render.h"
-
-using namespace std;
-
-namespace gnash
-{
-
-// Forward declarations
-
-// @@ should be found somewhere else I guess..
-//movie_interface* create_instance();
-
-void
-movieclip_init(as_object* /* global */)
-{
-#if 0
- // This is going to be the global MovieClip "class"/"function"
- static as_function *func=new function_as_object();
-
- // We make the 'prototype' element be a reference to
- // the __proto__ element
- as_object* proto = func->m_prototype;
- proto->add_ref();
-
- proto->set_member("constructor", func); //as_value(func));
- proto->set_member_flags("constructor", 1);
-
- func->set_member("prototype", as_value(proto));
-
- // Register _global.Function
- global->set_member("Function", func);
-#endif
-}
-
-} // namespace gnash
-
Index: server/MovieClip.h
===================================================================
RCS file: server/MovieClip.h
diff -N server/MovieClip.h
--- server/MovieClip.h 7 May 2006 12:19:06 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,51 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-
-#ifndef GNASH_MOVIECLIP_H
-#define GNASH_MOVIECLIP_H
-
-namespace gnash
-{
-
-class as_object;
-
-/// Initialize the global MovieClip constructor
-void movieclip_init(as_object* global);
-
-} // namespace gnash
-
-#endif // GNASH_MOVIECLIP_H
Index: server/Object.h
===================================================================
RCS file: server/Object.h
diff -N server/Object.h
--- server/Object.h 8 May 2006 11:43:58 -0000 1.11
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,46 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-
-#warning Object.h header has been split, do not include it directly
-
-#ifndef GNASH_OBJECT_H
-#define GNASH_OBJECT_H
-
-namespace gnash {
-} // namespace gnash
-
-#endif // GNASH_OBJECT_H
Index: server/action_buffer.cpp
===================================================================
RCS file: server/action_buffer.cpp
diff -N server/action_buffer.cpp
--- server/action_buffer.cpp 21 Aug 2006 12:54:47 -0000 1.18
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,479 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "action_buffer.h"
-#include "ActionExec.h"
-#include "log.h"
-#include "stream.h"
-
-#include "swf.h"
-#include "ASHandlers.h"
-#include "as_environment.h"
-
-#include <typeinfo>
-
-#if !defined(_WIN32) && !defined(WIN32)
-# include <pthread.h>
-#endif
-
-#include <string>
-#include <stdlib.h> // for strtod
-
-using namespace gnash;
-using namespace SWF;
-using std::string;
-using std::endl;
-
-
-namespace gnash {
-
-static const SWFHandlers& ash = SWFHandlers::instance();
-
-action_buffer::action_buffer()
- :
- m_decl_dict_processed_at(-1)
-{
-// static int count=0;
-// printf("Action buffer %d created\n", ++count);
-}
-
-
-void
-action_buffer::read(stream* in)
-{
- // Read action bytes.
- for (;;) {
-#if 0
- size_t instruction_start = m_buffer.size();
- size_t pc = m_buffer.size();
-#endif
-
- uint8_t action_id = in->read_u8();
- m_buffer.push_back(action_id);
-
- if (action_id & 0x80) {
- // Action contains extra data. Read it.
- uint16_t length = in->read_u16();
- m_buffer.push_back(length & 0x0FF);
- m_buffer.push_back((length >> 8) & 0x0FF);
- for (uint16_t i = 0; i < length; i++) {
- uint8_t b = in->read_u8();
- m_buffer.push_back(b);
- }
- }
-
- if (action_id == SWF::ACTION_END)
- {
- // end of action buffer.
- break;
- }
- }
-}
-
-
-/*public*/
-void
-action_buffer::process_decl_dict(size_t start_pc, size_t stop_pc) const
-{
- assert(stop_pc <= m_buffer.size());
-
- if (static_cast<size_t>(m_decl_dict_processed_at) == start_pc) {
- // We've already processed this decl_dict.
-#ifndef NDEBUG
- int count = read_int16(start_pc+3);
- assert((int) m_dictionary.size() == count);
-#endif
- return;
- }
-
- if (m_decl_dict_processed_at != -1) {
- log_error("process_decl_dict(%zd, %zd): decl_dict was already processed
at %d\n",
- start_pc,
- stop_pc,
- m_decl_dict_processed_at);
- return;
- }
-
- m_decl_dict_processed_at = start_pc;
-
- // Actual processing.
- size_t i = start_pc;
- int16 length = read_int16(i+1);
- int16 count = read_int16(i+3);
- i += 2;
-
-//log_msg("Start at %d, stop at %d, length read was %d, count read was %d",
start_pc, stop_pc, length, count);
-
- assert(start_pc + 3 + length == stop_pc);
-
- m_dictionary.resize(count);
-
- // Index the strings.
- for (int ct = 0; ct < count; ct++) {
- // Point into the current action buffer.
- m_dictionary[ct] = (const char*) &m_buffer[3 + i];
-
- while (m_buffer[3 + i]) {
- // safety check.
- if (i >= stop_pc) {
- log_error("action buffer dict length exceeded\n");
-
- // Jam something into the remaining (invalid) entries.
- while (ct < count) {
- m_dictionary[ct] = "<invalid>";
- ct++;
- }
- return;
- }
- i++;
- }
- i++;
- }
-}
-
-// Interpret the actions in this action buffer, and evaluate
-// them in the given environment. Execute our whole buffer,
-// without any arguments passed in.
-void
-action_buffer::execute(as_environment* env) const
-{
- assert(env);
-
- int local_stack_top = env->get_local_frame_top();
- env->add_frame_barrier();
-
- ActionExec exec(*this, *env);
- exec();
-
- env->set_local_frame_top(local_stack_top);
-}
-
-// Interpret the specified subset of the actions in our
-// buffer. Caller is responsible for cleaning up our local
-// stack frame (it may have passed its arguments in via the
-// local stack frame).
-//
-// The is_function2 flag determines whether to use global or local registers.
-void
-action_buffer::execute(
- as_environment* env,
- size_t start_pc,
- size_t exec_bytes, // used when invoked as a function call
- as_value* retval, // used when invoked as a function call
- const std::vector<with_stack_entry>& initial_with_stack,
- bool is_function2) const
-{
- assert(env);
- ActionExec exec(*this, *env, start_pc, exec_bytes, retval,
- initial_with_stack, is_function2);
- exec();
-}
-
-// Disassemble one instruction to the log.
-static void
-disasm(const unsigned char* instruction_data)
-{
-
- as_arg_t fmt = ARG_HEX;
- action_type action_id = (action_type)instruction_data[0];
- unsigned char num[10];
- memset(num, 0, 10);
-
- dbglogfile.setStamp(false);
- // Show instruction.
- if (action_id > ash.lastType()) {
- dbglogfile << "<unknown>[0x" << action_id << "]" << endl;
- } else {
- dbglogfile << ash[action_id].getName().c_str() << endl;
- fmt = ash[action_id].getArgFormat();
- }
-
- // Show instruction argument(s).
- if (action_id & 0x80) {
- assert(fmt != ARG_NONE);
- int length = instruction_data[1] | (instruction_data[2] << 8);
- if (fmt == ARG_HEX) {
- for (int i = 0; i < length; i++) {
- hexify(num, (const unsigned char *)&instruction_data[3 + i], 1,
false);
- dbglogfile << "0x" << num << " ";
-// dbglogfile << instruction_data[3 + i] << " ";
- }
- dbglogfile << endl;
- } else if (fmt == ARG_STR) {
- string str;
- for (int i = 0; i < length; i++) {
- str = instruction_data[3 + i];
- }
- dbglogfile << "\"" << str.c_str() << "\"" << endl;
- } else if (fmt == ARG_U8) {
- int val = instruction_data[3];
- dbglogfile << " " << val << endl;
- } else if (fmt == ARG_U16) {
- int val = instruction_data[3] | (instruction_data[4] << 8);
- dbglogfile << " " << val << endl;
- } else if (fmt == ARG_S16) {
- int val = instruction_data[3] | (instruction_data[4] << 8);
- if (val & 0x8000) val |= ~0x7FFF; // sign-extend
- dbglogfile << " " << val << endl;
- } else if (fmt == ARG_PUSH_DATA) {
- dbglogfile << endl;
- int i = 0;
- while (i < length) {
- int type = instruction_data[3 + i];
- i++;
- if (type == 0) {
- // string
- string str;
- while (instruction_data[3 + i]) {
- str += instruction_data[3 + i];
- i++;
- }
- i++;
- dbglogfile << "\t\"" << str.c_str() << "\"" << endl;
- } else if (type == 1) {
- // float (little-endian)
- union {
- float f;
- uint32_t i;
- } u;
- compiler_assert(sizeof(u) == sizeof(u.i));
-
- memcpy(&u.i, instruction_data + 3 + i, 4);
- u.i = swap_le32(u.i);
- i += 4;
-
- dbglogfile << "(float) " << u.f << endl;
- } else if (type == 2) {
- dbglogfile << "NULL" << endl;
- } else if (type == 3) {
- dbglogfile << "undef" << endl;
- } else if (type == 4) {
- // contents of register
- int reg = instruction_data[3 + i];
- i++;
- dbglogfile << "reg[" << reg << "]" << endl;
- } else if (type == 5) {
- int bool_val = instruction_data[3 + i];
- i++;
- dbglogfile << "bool(" << bool_val << ")" << endl;
- } else if (type == 6) {
- // double
- // wacky format: 45670123
- union {
- double d;
- uint64 i;
- struct {
- uint32_t lo;
- uint32_t hi;
- } sub;
- } u;
- compiler_assert(sizeof(u) == sizeof(u.i));
-
- memcpy(&u.sub.hi, instruction_data + 3 + i, 4);
- memcpy(&u.sub.lo, instruction_data + 3 + i + 4, 4);
- u.i = swap_le64(u.i);
- i += 8;
-
- dbglogfile << "(double) " << u.d << endl;
- } else if (type == 7) {
- // int32
- int32_t val = instruction_data[3 + i]
- | (instruction_data[3 + i + 1] << 8)
- | (instruction_data[3 + i + 2] << 16)
- | (instruction_data[3 + i + 3] << 24);
- i += 4;
- dbglogfile << "(int) " << val << endl;
- } else if (type == 8) {
- int id = instruction_data[3 + i];
- i++;
- dbglogfile << "dict_lookup[" << id << "]" << endl;
- } else if (type == 9) {
- int id = instruction_data[3 + i] | (instruction_data[3 + i
+ 1] << 8);
- i += 2;
- dbglogfile << "dict_lookup_lg[" << id << "]" << endl;
- }
- }
- } else if (fmt == ARG_DECL_DICT) {
- int i = 0;
- int count = instruction_data[3 + i] | (instruction_data[3 + i + 1]
<< 8);
- i += 2;
-
- dbglogfile << " [" << count << "]" << endl;
-
- // Print strings.
- for (int ct = 0; ct < count; ct++) {
- dbglogfile << "\t" << endl; // indent
-
- string str;
- while (instruction_data[3 + i]) {
- // safety check.
- if (i >= length) {
- dbglogfile << "<disasm error -- length exceeded>" <<
endl;
- break;
- }
- str += instruction_data[3 + i];
- i++;
- }
- dbglogfile << "\"" << str.c_str() << "\"" << endl;
- i++;
- }
- } else if (fmt == ARG_FUNCTION2) {
- // Signature info for a function2 opcode.
- int i = 0;
- const char* function_name = (const char*) &instruction_data[3 + i];
- i += strlen(function_name) + 1;
-
- int arg_count = instruction_data[3 + i] | (instruction_data[3 + i +
1] << 8);
- i += 2;
-
- int reg_count = instruction_data[3 + i];
- i++;
-
- dbglogfile << "\t\tname = '" << function_name << "'"
- << " arg_count = " << arg_count
- << " reg_count = " << reg_count << endl;
-
- uint16 flags = (instruction_data[3 + i]) | (instruction_data[3
+ i + 1] << 8);
- i += 2;
-
- // @@ What is the difference between "super" and "_parent"?
-
- bool preload_global = (flags & 0x100) != 0;
- bool preload_parent = (flags & 0x80) != 0;
- bool preload_root = (flags & 0x40) != 0;
- bool suppress_super = (flags & 0x20) != 0;
- bool preload_super = (flags & 0x10) != 0;
- bool suppress_args = (flags & 0x08) != 0;
- bool preload_args = (flags & 0x04) != 0;
- bool suppress_this = (flags & 0x02) != 0;
- bool preload_this = (flags & 0x01) != 0;
-
- log_msg("\t\t pg = %d\n"
- "\t\t pp = %d\n"
- "\t\t pr = %d\n"
- "\t\tss = %d, ps = %d\n"
- "\t\tsa = %d, pa = %d\n"
- "\t\tst = %d, pt = %d\n",
- int(preload_global),
- int(preload_parent),
- int(preload_root),
- int(suppress_super),
- int(preload_super),
- int(suppress_args),
- int(preload_args),
- int(suppress_this),
- int(preload_this));
-
- for (int argi = 0; argi < arg_count; argi++) {
- int arg_register = instruction_data[3 + i];
- i++;
- const char* arg_name = (const char*) &instruction_data[3 +
i];
- i += strlen(arg_name) + 1;
-
- dbglogfile << "\t\targ[" << argi << "]"
- << " - reg[" << arg_register << "]"
- << " - '" << arg_name << "'" << endl;
- }
-
- int function_length = instruction_data[3 + i] | (instruction_data[3
+ i + 1] << 8);
- i += 2;
-
- dbglogfile << "\t\tfunction length = " << function_length << endl;
- }
- } else {
- dbglogfile << endl;
- }
- dbglogfile.setStamp(true);
-}
-
-// Disassemble one instruction to the log.
-void
-action_buffer::log_disasm(size_t pc) const
-{
- const unsigned char* instruction_data =
- (const unsigned char *)&m_buffer[pc];
- disasm(instruction_data);
-}
-
-
-float
-action_buffer::read_float_little(size_t pc) const
-{
- union {
- float f;
- uint32_t i;
- } u;
- compiler_assert(sizeof(u) == sizeof(u.i));
- memcpy(&u.i, &m_buffer[pc], 4);
- u.i = swap_le32(u.i);
- return u.f;
-}
-
-double
-action_buffer::read_double_wacky(size_t pc) const
-{
- // double
- // wacky format: 45670123
- union {
- double d;
- uint64 i;
- struct {
- uint32_t lo;
- uint32_t hi;
- } sub;
- } u;
-
- compiler_assert(sizeof(u) == sizeof(u.i));
-
- // this works, but is pretty dirty
- memcpy(&u.sub.hi, &m_buffer[pc], 4);
- memcpy(&u.sub.lo, &m_buffer[pc + 4], 4);
- u.i = swap_le64(u.i);
-
- return u.d;
-}
-
-}
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/action_buffer.h
===================================================================
RCS file: server/action_buffer.h
diff -N server/action_buffer.h
--- server/action_buffer.h 4 Aug 2006 14:45:52 -0000 1.5
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,284 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-//
-
-#ifndef GNASH_ACTION_BUFFER_H
-#define GNASH_ACTION_BUFFER_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-#include "gnash.h"
-//#include "as_object.h"
-#include "types.h"
-#include <wchar.h>
-
-#include "container.h"
-#include "smart_ptr.h"
-//#include "log.h"
-#include "with_stack_entry.h"
-
-// Forward declarations
-namespace gnash {
- struct as_environment;
- struct as_value;
- namespace SWF {
- class ActionHandler;
- }
-}
-
-
-namespace gnash {
-
-class ActionExec;
-
-/// A code segment.
-//
-/// This currently holds the actions in a memory
-/// buffer, but I'm workin toward making this unneeded
-/// so to eventually use a gnash::stream directly and
-/// avoid full loads. (not before profiling!).
-//
-class action_buffer
-{
-
-public:
-
- friend class ActionExec;
-
- action_buffer();
-
- /// Read action bytes from input stream
- void read(stream* in);
-
- /// \brief
- /// Interpret the actions in this action buffer, and evaluate
- /// them in the given environment.
- //
- /// Execute our whole buffer,
- /// without any arguments passed in.
- ///
- /// FIXME: obsolete this, use ActionExec instead.
- ///
- void execute(as_environment* env) const;
-
- /// Interpret the specified subset of the actions in our buffer.
- //
- /// Caller is responsible for cleaning up our local
- /// stack frame (it may have passed its arguments in via the
- /// local stack frame).
- ///
- /// FIXME: obsolete this, use ActionExec instead.
- ///
- void execute(
- as_environment* env,
- size_t start_pc,
- size_t exec_bytes,
- as_value* retval, // we should probably drop this parameter
- const std::vector<with_stack_entry>& initial_with_stack,
- bool is_function2) const;
-
- bool is_null() const
- {
- return m_buffer.size() < 1 || m_buffer[0] == 0;
- }
-
- // kept for backward compatibility, should drop and see
- // what breaks.
- size_t get_length() const { return size(); }
-
- size_t size() const { return m_buffer.size(); }
-
- uint8_t operator[] (size_t off) const
- {
- assert(off < m_buffer.size() );
- return m_buffer[off];
- }
-
- /// Disassemble instruction at given offset to the log.
- void log_disasm(size_t pc) const;
-
- /// Get a null-terminated string from given offset
- //
- /// Useful to hide complexity of underlying buffer access.
- ///
- const char* read_string(size_t pc) const
- {
- return (const char*)(&m_buffer[pc]);
- }
-
- /// Get an integer value from given offset
- //
- /// Useful to hide complexity of underlying buffer access.
- ///
- int16_t read_int16(size_t pc) const
- {
- int ret = m_buffer[pc] | (m_buffer[pc + 1] << 8);
- return ret;
- }
-
- /// Read a 32-bit integer starting at given offset.
- //
- /// Useful to hide complexity of underlying buffer access.
- ///
- int32_t read_int32(size_t pc) const
- {
- int32_t val = m_buffer[pc]
- | (m_buffer[pc + 1] << 8)
- | (m_buffer[pc + 2] << 16)
- | (m_buffer[pc + 3] << 24);
- return val;
- }
-
- /// Read a little-endian 32-bit float starting at given offset
- //
- /// Useful to hide complexity of underlying buffer access.
- ///
- float read_float_little(size_t pc) const;
-
- /// Read a 64-bit double starting at given offset.
- //
- /// wacky format: 45670123
- /// Useful to hide complexity of underlying buffer access.
- ///
- double read_double_wacky(size_t pc) const;
-
- /// Return number of entries in the constant pool
- size_t dictionary_size() const
- {
- return m_dictionary.size();
- }
-
- /// Return a value from the constant pool
- const char* dictionary_get(size_t n) const
- {
- return m_dictionary[n];
- }
-
- /// \brief
- /// Interpret the SWF::ACTION_CONSTANTPOOL opcode.
- //
- /// Don't read stop_pc or later.
- ///
- /// A dictionary is some static strings embedded in the
- /// action buffer; there should only be one dictionary per
- /// action buffer.
- ///
- /// NOTE: Normally the dictionary is declared as the first
- /// action in an action buffer, but I've seen what looks like
- /// some form of copy protection that amounts to:
- ///
- /// <start of action buffer>
- /// push true
- /// branch_if_true label
- /// decl_dict [0] // this is never executed, but has lots
of orphan data declared in the opcode
- /// label: // (embedded inside the previous opcode; looks like an
invalid jump)
- /// ... "protected" code here, including the real decl_dict
opcode ...
- /// <end of the dummy decl_dict [0] opcode>
- ///
- /// So we just interpret the first decl_dict we come to, and
- /// cache the results. If we ever hit a different decl_dict in
- /// the same action_buffer, then we log an error and ignore it.
- ///
- void process_decl_dict(size_t start_pc, size_t stop_pc) const;
-
-private:
-
- // Don't put these as values in std::vector<>! They contain
- // internal pointers and cannot be moved or copied.
- // If you need to keep an array of them, keep pointers
- // to new'd instances.
- action_buffer(const action_buffer& /*a*/) { assert(0); }
-
- /// the code itself, as read from the SWF
- std::vector<uint8_t> m_buffer;
-
- /// The dictionary
- mutable std::vector<const char*> m_dictionary;
-
- /// FIXME: move to ActionExec
- mutable int m_decl_dict_processed_at;
-
-#if 0
- void doActionNew(as_environment* env,
- std::vector<with_stack_entry>& with_stack);
-
- void doActionInstanceOf(as_environment* env);
-
- void doActionCast(as_environment* env);
-
- void doActionCallMethod(as_environment* env);
-
- void doActionCallFunction(as_environment* env,
- std::vector<with_stack_entry>& with_stack);
-
- void doActionDefineFunction(as_environment* env,
- std::vector<with_stack_entry>& with_stack,
- size_t pc, size_t* next_pc);
-
- void doActionDefineFunction2(as_environment* env,
- std::vector<with_stack_entry>& with_stack,
- size_t pc, size_t* next_pc);
-
- void doActionGetMember(as_environment* env);
-
- void doActionStrictEquals(as_environment* env);
-
- void doActionEquals(as_environment* env);
-
- void doActionDelete(as_environment* env,
- std::vector<with_stack_entry>& with_stack);
-
- void doActionDelete2(as_environment* env,
- std::vector<with_stack_entry>& with_stack);
-#endif
-
-};
-
-
-} // end namespace gnash
-
-
-#endif // GNASH_ACTION_BUFFER_H
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/bitmap_character_def.h
===================================================================
RCS file: server/bitmap_character_def.h
diff -N server/bitmap_character_def.h
--- server/bitmap_character_def.h 7 May 2006 19:40:43 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,114 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-//
-
-#ifndef GNASH_BITMAP_CHARACTER_DEF_H
-#define GNASH_BITMAP_CHARACTER_DEF_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gnash.h" // for bitmap_info definition
-#include "character_def.h" // for character_def inheritance
-#include "action.h"
-#include "types.h"
-#include "log.h"
-#include "container.h"
-#include "utility.h"
-#include "smart_ptr.h"
-//#include "movie_interface.h"
-#include <stdarg.h>
-
-#include <cassert>
-
-namespace gnash {
-
-/// What's this ? An interface ?
-struct bitmap_character_def : public character_def
-{
- virtual gnash::bitmap_info* get_bitmap_info() = 0;
-};
-
-#if 1
-/// Bitmap character
-struct bitmap_character : public bitmap_character_def
-{
- bitmap_character(bitmap_info* bi)
- :
- m_bitmap_info(bi)
- {
- }
-
-// bitmap_character(image::rgb* image)
-// {
-// assert(image != 0);
-
-// // Create our bitmap info, from our image.
-// m_bitmap_info =
gnash::render::create_bitmap_info_rgb(image);
-// }
-
-// bitmap_character(image::rgba* image)
-// {
-// assert(image != 0);
-
-// // Create our bitmap info, from our image.
-// m_bitmap_info =
gnash::render::create_bitmap_info_rgba(image);
-// }
-
- gnash::bitmap_info* get_bitmap_info()
- {
- return m_bitmap_info.get_ptr();
- }
-
-private:
- smart_ptr<gnash::bitmap_info> m_bitmap_info;
-};
-
-#endif
-
-
-} // end namespace gnash
-
-
-#endif // GNASH_BITMAP_CHARACTER_DEF_H
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/character_def.cpp
===================================================================
RCS file: server/character_def.cpp
diff -N server/character_def.cpp
--- server/character_def.cpp 1 Jul 2006 20:44:10 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,60 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-//
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <character_def.h>
-#include <generic_character.h>
-
-namespace gnash
-{
-
-character*
-character_def::create_character_instance(character* parent, int id)
-{
- return new generic_character(this, parent, id);
-}
-
-}
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/character_def.h
===================================================================
RCS file: server/character_def.h
diff -N server/character_def.h
--- server/character_def.h 27 Jul 2006 01:47:11 -0000 1.8
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,132 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-
-#ifndef GNASH_CHARACTER_DEF_H
-#define GNASH_CHARACTER_DEF_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "resource.h" // for inheritance from resource class
-
-// Forward declarations
-class tu_file;
-namespace gnash {
- class character;
- struct cache_options;
- //class sprite_instance;
-}
-
-namespace gnash {
-
-/// Immutable data representing the template of a movie element.
-//
-/// This is not really a public interface. It's here so it
-/// can be mixed into movie_definition and sprite_definition,
-/// without using multiple inheritance.
-///
-struct character_def : public resource
-{
-private:
- int m_id;
-
-public:
- character_def()
- :
- m_id(-1)
- {
- }
-
- virtual ~character_def() {}
-
- virtual void display(character* /*instance_info*/)
- {
- }
-
- virtual bool point_test_local(float /*x*/, float /*y*/)
- {
- return false;
- }
-
- virtual float get_height_local()
- {
- return 0.0f;
- }
-
- virtual float get_width_local()
- {
- return 0.0f;
- }
-
- /// Should stick the result in a smart_ptr immediately.
- //
- /// default is to make a generic_character
- ///
- virtual character* create_character_instance(character* parent,
- int id);
-
- // From resource interface.
- virtual character_def* cast_to_character_def()
- {
- return this;
- }
-
- //
- // Caching.
- //
-
- virtual void output_cached_data(tu_file* /*out*/,
- const cache_options& /*options*/)
- {
- }
-
- virtual void input_cached_data(tu_file* /*in*/)
- {
- }
-};
-
-
-} // namespace gnash
-
-#endif // GNASH_CHARACTER_DEF_H
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/edit_text_character_def.cpp
===================================================================
RCS file: server/edit_text_character_def.cpp
diff -N server/edit_text_character_def.cpp
--- server/edit_text_character_def.cpp 13 Aug 2006 16:45:11 -0000 1.9
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,137 +0,0 @@
-// text.cpp -- Thatcher Ulrich <address@hidden> 2003
-
-// This source code has been donated to the Public Domain. Do
-// whatever you want with it.
-
-// Code for the text tags.
-
-
-#include "stream.h"
-#include "log.h"
-#include "movie_definition.h" // for m_root_def use
-
-#include "edit_text_character_def.h"
-#include "edit_text_character.h"
-
-namespace gnash {
-
-// Forward declarations
-struct movie_definition;
-
-void
-edit_text_character_def::read(stream* in, int tag_type,
- movie_definition* m)
-{
- assert(m != NULL);
- assert(tag_type == SWF::DEFINEEDITTEXT); // 37
-
- m_rect.read(in);
-
- in->align();
- bool has_text = in->read_uint(1) ? true : false;
- m_word_wrap = in->read_uint(1) ? true : false;
- m_multiline = in->read_uint(1) ? true : false;
- m_password = in->read_uint(1) ? true : false;
- m_readonly = in->read_uint(1) ? true : false;
- bool has_color = in->read_uint(1) ? true : false;
- bool has_max_length = in->read_uint(1) ? true : false;
- bool has_font = in->read_uint(1) ? true : false;
-
- in->read_uint(1); // reserved
- m_auto_size = in->read_uint(1) ? true : false;
- bool has_layout = in->read_uint(1) ? true : false;
- m_no_select = in->read_uint(1) ? true : false;
- m_border = in->read_uint(1) ? true : false;
- in->read_uint(1); // reserved
- m_html = in->read_uint(1) ? true : false;
- m_use_outlines = in->read_uint(1) ? true : false;
-
- if (has_font)
- {
- m_font_id = in->read_u16();
- m_text_height = in->read_u16();
- }
-
- if (has_color)
- {
- m_color.read_rgba(in);
- }
-
- if (has_max_length)
- {
- m_max_length = in->read_u16();
- }
-
- if (has_layout)
- {
- m_alignment = (alignment) in->read_u8();
- //m_left_margin = (float) in->read_u16();
- m_left_margin = in->read_u16();
- //m_right_margin = (float) in->read_u16();
- m_right_margin = in->read_u16();
- m_indent = in->read_s16();
- m_leading = in->read_s16();
- }
-
- char* name = in->read_string();
- m_default_name = name;
- delete [] name;
-
- if (has_text)
- {
- char* str = in->read_string();
- m_default_text = str;
- delete [] str;
- }
-
- IF_VERBOSE_PARSE (
- log_parse("edit_text_char:\n"
- " default varname = %s\n"
- " text = ``%s''\n"
- " font_id: %d\n"
- " text_height: %d",
- m_default_name.c_str(),
- m_default_text.c_str(),
- m_font_id,
- m_text_height);
- );
-}
-
-const font*
-edit_text_character_def::get_font()
-{
- if (m_font == NULL)
- {
- // Resolve the font, if possible.
- m_font = m_root_def->get_font(m_font_id);
- if (m_font == NULL)
- {
- log_error("error: text style with undefined font;
font_id = %d\n", m_font_id);
- }
- }
-
- return m_font;
-}
-
-character*
-edit_text_character_def::create_character_instance(character* parent,
- int id)
-{
- // Resolve the font, if possible
- get_font();
- edit_text_character* ch = new edit_text_character(parent, this, id);
-
- ch->set_name(m_default_name.c_str());
-
- return ch;
-}
-
-
-} // namespace gnash
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
-
Index: server/edit_text_character_def.h
===================================================================
RCS file: server/edit_text_character_def.h
diff -N server/edit_text_character_def.h
--- server/edit_text_character_def.h 10 Jul 2006 13:47:12 -0000 1.8
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,308 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-
-
-#ifndef _GNASH_EDIT_TEXT_CHARACTER_DEF_H_
-#define _GNASH_EDIT_TEXT_CHARACTER_DEF_H_
-
-#include "character_def.h" // for inheritance
-#include "gnash.h" // for composition (struct rect)
-#include "textformat.h" // for composition
-
-namespace gnash {
-
-// Forward declarations
-struct movie_definition;
-
-/// \brief
-/// A definition for a text display character, whose text can
-/// be changed at runtime (by script or host).
-/// This object is defined by SWF tag 37 (SWF::DEFINEEDITTEXT)
-///
-class edit_text_character_def : public character_def
-{
-
-public:
-
- /// Text alignment values
- enum alignment
- {
- ALIGN_LEFT = 0,
- ALIGN_RIGHT,
- ALIGN_CENTER,
- /// probably don't need to implement...
- ALIGN_JUSTIFY
- };
-
- edit_text_character_def(movie_definition* root_def)
- :
- m_root_def(root_def),
- m_format(),
- m_word_wrap(false),
- m_multiline(false),
- m_password(false),
- m_readonly(false),
- m_auto_size(false),
- m_no_select(false),
- m_border(false),
- m_html(false),
- m_use_outlines(false),
- m_font_id(-1),
- m_font(NULL),
- m_text_height(1),
- m_max_length(0),
- m_alignment(ALIGN_LEFT),
- m_left_margin(0),
- m_right_margin(0),
- m_indent(0),
- m_leading(0)
- {
- assert(m_root_def);
-
- m_color.set(0, 0, 0, 255);
- }
-
- /// Set the format of the text
- void set_format(text_format &format)
- {
- m_format = format;
- }
-
- ~edit_text_character_def()
- {
- }
-
- /// Get width of this definition (by definition)
- float width() const { return m_rect.width(); }
-
- /// Get height of this definition (by definition)
- float height() const { return m_rect.height(); }
-
- /// Create an instance of this character
- character* create_character_instance(character* parent, int id);
-
- /// Initialize from SWF input stream (tag 37)
- void read(stream* in, int tag_type, movie_definition* m);
-
- /// Return a reference to the default text associated
- /// with this EditText definition.
- const tu_string& get_default_text() const {
- return m_default_text;
- }
-
- /// Return a reference to the default name for
- /// instances of this EditText definition. (?)
- const tu_string& get_default_name() const {
- return m_default_name;
- }
-
- /// \brief
- /// Return the maximum length of text this widget
- /// can hold.
- int get_max_length() const {
- return m_max_length;
- }
-
- /// Get boundaries of this movie
- //
- /// Return a reference to private space, copy
- /// it if you need it for longer then this
- /// object's lifetime.
- ///
- const rect& get_bounds() const {
- return m_rect;
- }
-
- /// Get right margin in twips
- uint16_t get_right_margin() const {
- return m_right_margin;
- }
-
- /// Get left margin in twips
- uint16_t get_left_margin() const {
- return m_left_margin;
- }
-
- /// Get indentation in twips
- uint16_t get_indent() const {
- return m_indent;
- }
-
- /// Get height of font in twips.
- // @@ what if has_font is false ??
- uint16_t get_font_height() const {
- return m_text_height;
- }
-
- /// Get font.
- //
- /// Note: use add_ref() on the return if you need to keep
- /// it alive after this definition gets destructed.
- ///
- const font* get_font();
-
- /// Get color of the text
- const rgba& get_text_color() const {
- return m_color;
- }
-
- /// \brief
- /// Get extra space between lines (in twips).
- //
- /// This is in addition to default font line spacing.
- uint16_t get_leading() const {
- return m_leading;
- }
-
- /// Get text alignment
- alignment get_alignment() const {
- return m_alignment;
- }
-
- /// Is border requested ?
- bool has_border() const {
- return m_border;
- }
-
- /// Word wrap requested ?
- bool do_word_wrap() const {
- return m_word_wrap;
- }
-
- /// Get root movie definition
- movie_definition* get_root_def() {
- return m_root_def;
- }
-
- bool get_readonly() const
- {
- return m_readonly;
- }
-
-private:
-
- /// Root movie_definition
- movie_definition* m_root_def;
-
- rect m_rect;
- tu_string m_default_name;
- text_format m_format;
- bool m_word_wrap;
- bool m_multiline;
- /// show asterisks instead of actual characters
- bool m_password;
- bool m_readonly;
- /// resize our bound to fit the text
- bool m_auto_size;
- bool m_no_select;
-
- /// forces white background and black border.
- /// silly, but sometimes used
- bool m_border;
-
- /// Allowed HTML (from Alexi's SWF Reference).
- //
- /// <a href=url target=targ>...</a> -- hyperlink
- /// <b>...</b> -- bold
- /// <br> -- line break
- /// <font face=name size=[+|-][0-9]+ color=#RRGGBB>...</font> -- font
change; size in TWIPS
- /// <i>...</i> -- italic
- /// <li>...</li> -- list item
- /// <p>...</p> -- paragraph
- /// <tab> -- insert tab
- /// <TEXTFORMAT> </TEXTFORMAT>
- /// [ BLOCKINDENT=[0-9]+ ]
- /// [ INDENT=[0-9]+ ]
- /// [ LEADING=[0-9]+ ]
- /// [ LEFTMARGIN=[0-9]+ ]
- /// [ RIGHTMARGIN=[0-9]+ ]
- /// [ TABSTOPS=[0-9]+{,[0-9]+} ]
- ///
- /// Change the different parameters as indicated. The
- /// sizes are all in TWIPs. There can be multiple
- /// positions for the tab stops. These are seperated by
- /// commas.
- /// <U>...</U> -- underline
- ///
- bool m_html;
-
-
-
- /// \brief
- /// When true, use specified SWF internal font.
- /// Otherwise, renderer picks a default font
- bool m_use_outlines;
-
- int m_font_id;
- font* m_font;
-
- /// height of font text, in twips
- uint16_t m_text_height;
-
- /// Text color
- rgba m_color;
-
- /// Maximum length of text this widget can display (number of chars?)
- int m_max_length;
-
- alignment m_alignment;
-
- /// extra space between box's left border and text (in twips)
- uint16_t m_left_margin;
- //float m_left_margin;
-
- /// extra space between box's right border and text (in twips)
- uint16_t m_right_margin;
- //float m_right_margin;
-
- /// how much to indent the first line of multiline text (in twips)
- uint16_t m_indent;
- //float m_indent;
-
- /// \brief
- /// Extra space between lines
- /// (in addition to default font line spacing)
- uint16_t m_leading;
-
- /// The default text to be displayed
- tu_string m_default_text;
-
-};
-
-} // namespace gnash
-
-#endif // _GNASH_EDIT_TEXT_CHARACTER_DEF_H_
Index: server/movie_def_impl.cpp
===================================================================
RCS file: server/movie_def_impl.cpp
diff -N server/movie_def_impl.cpp
--- server/movie_def_impl.cpp 23 Aug 2006 22:22:56 -0000 1.35
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,1024 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-#ifdef HAVE_PTHREADS
-#include <pthread.h>
-#endif
-
-#include <iostream>
-#include <string>
-
-#include "movie_def_impl.h"
-#include "movie_definition.h" // for inheritance
-#include "movie_instance.h"
-#include "tu_file.h"
-#include "zlib_adapter.h"
-#include "stream.h"
-#include "jpeg.h"
-#include "fontlib.h"
-#include "font.h"
-#include "log.h"
-//#include "Sprite.h"
-#include "sprite_instance.h"
-#include "render.h"
-#include "bitmap_character_def.h"
-#include "smart_ptr.h"
-#include "swf/TagLoadersTable.h"
-#include "execute_tag.h"
-#include "movie_root.h"
-
-using namespace std;
-
-// Increment this when the cache data format changes.
-#define CACHE_FILE_VERSION 4
-
-// If != 0 this is the number of frames to load at each iteration
-// of the main loop. Loading in chunks greatly speeds the process up
-#define FRAMELOAD_CHUNK 0
-
-// Debug frames load
-#undef DEBUG_FRAMES_LOAD
-
-// Define this this to load movies using a separate thread
-// (undef and it will fully load a movie before starting to play it)
-#define LOAD_MOVIES_IN_A_SEPARATE_THREAD 1
-
-// Debug threads locking
-#undef DEBUG_THREADS_LOCKING
-
-namespace gnash
-{
-
-#ifdef USE_SDL_THREADS
-
-MovieLoader::MovieLoader(movie_def_impl& md)
- :
- _waiting_for_frame(0),
- _movie_def(md)
-{
- _frame_reached_condition = SDL_CreateCond();
- _mutex = SDL_CreateMutex();
-}
-
-MovieLoader::~MovieLoader()
-{
- SDL_DestroyMutex(_mutex);
- SDL_DestroyCond(_frame_reached_condition);
-}
-
-int MovieLoader::execute(void* arg)
-{
- movie_def_impl* md = static_cast<movie_def_impl*>(arg);
- md->read_all_swf();
- return 0;
-}
-
-bool MovieLoader::start()
-{
- _thread = SDL_CreateThread(execute, &_movie_def);
- if (_thread == NULL)
- {
- return false;
- }
- return true;
-}
-
-void MovieLoader::signal_frame_loaded(size_t frameno)
-{
- if (_waiting_for_frame &&
- frameno >= _waiting_for_frame )
- {
- SDL_CondSignal(_frame_reached_condition);
- }
-}
-
-void MovieLoader::wait_for_frame(size_t framenum)
-{
-
- lock();
-
- if (_movie_def.get_loading_frame() < framenum)
- {
- //log_msg("Waiting for frame %u to load", framenum);
-
- assert(_waiting_for_frame == 0);
- _waiting_for_frame = framenum;
-
- do
- {
- SDL_CondWait(_frame_reached_condition, _mutex);
- }
- while (_movie_def.get_loading_frame() < framenum);
-
- _waiting_for_frame = 0;
-
- //log_msg("Done waiting (frame %u/%u loaded)",
- // _movie_def.get_loading_frame(),
- // _movie_def.get_frame_count());
- }
-
- unlock();
-}
-
-void MovieLoader::lock()
-{
- if ( -1 == SDL_mutexP(_mutex) )
- {
- log_error("Error unlocking MovieLoader");
- }
-}
-
-void MovieLoader::unlock()
-{
- if ( -1 == SDL_mutexV(_mutex) )
- {
- log_error("Error unlocking MovieLoader");
- }
-}
-
-#else
-
-MovieLoader::MovieLoader(movie_def_impl& md)
- :
- _waiting_for_frame(0),
- _movie_def(md)
-{
- pthread_cond_init(&_frame_reached_condition, NULL);
- pthread_mutex_init(&_mutex, NULL);
-}
-
-MovieLoader::~MovieLoader()
-{
- if ( pthread_cond_destroy(&_frame_reached_condition) != 0 )
- {
- log_error("Error destroying MovieLoader condition");
- }
-
- if ( pthread_mutex_destroy(&_mutex) != 0 )
- {
- log_error("Error destroying MovieLoader mutex");
- }
-}
-
-void*
-MovieLoader::execute(void* arg)
-{
- movie_def_impl* md = static_cast<movie_def_impl*>(arg);
- md->read_all_swf();
- // maybe this frees all resources and that's bad !
- //pthread_exit(NULL);
-
- /* Better to cancel yourself methinks: 'man 3p pthread_cancel' */
- pthread_cancel(pthread_self());
- pthread_testcancel();
- return NULL;
-}
-
-bool
-MovieLoader::start()
-{
- if ( pthread_create(&_thread, NULL, execute, &_movie_def) )
- {
- return false;
- }
-
- // should set some mutexes ?
-
- return true;
-}
-
-void
-MovieLoader::signal_frame_loaded(size_t frameno)
-{
- if (_waiting_for_frame &&
- frameno >= _waiting_for_frame )
- {
- pthread_cond_signal(&_frame_reached_condition);
- }
-}
-
-void
-MovieLoader::lock()
-{
-
-#ifdef DEBUG_THREADS_LOCKING
- // debugging
- if ( pthread_equal(pthread_self(), _thread) ) {
- log_msg("MovieLoader locking itself");
- } else {
- log_msg("MovieLoader being locked by another thread");
- }
-#endif
-
- if ( pthread_mutex_lock(&_mutex) != 0 )
- {
- log_error("Error locking MovieLoader");
- }
-
-#ifdef DEBUG_THREADS_LOCKING
- // debugging
- if ( pthread_equal(pthread_self(), _thread) ) {
- log_msg("MovieLoader locked by itself");
- } else {
- log_msg("MovieLoader locked by another thread");
- }
-#endif
-}
-
-void
-MovieLoader::unlock()
-{
-
-#ifdef DEBUG_THREADS_LOCKING
- // debugging
- if ( pthread_equal(pthread_self(), _thread) ) {
- log_msg("MovieLoader unlocking itself");
- } else {
- log_msg("MovieLoader being unlocked by another thread");
- }
-#endif
-
- if ( pthread_mutex_unlock(&_mutex) != 0 )
- {
- log_error("Error unlocking MovieLoader");
- }
-
-#ifdef DEBUG_THREADS_LOCKING
- // debugging
- if ( pthread_equal(pthread_self(), _thread) ) {
- log_msg("MovieLoader unlocked itself");
- } else {
- log_msg("MovieLoader unlocked by another thread");
- }
-#endif
-}
-
-void
-MovieLoader::wait_for_frame(size_t framenum)
-{
-
- // lock the loader so we can rely on m_loading_frame
- lock();
-
- if ( _movie_def.get_loading_frame() < framenum )
- {
- assert(_waiting_for_frame == 0);
- _waiting_for_frame = framenum;
- pthread_cond_wait(&_frame_reached_condition, &_mutex);
- _waiting_for_frame = 0;
- }
-
- unlock();
-}
-
-#endif // PTHREAD MovieLoader
-
-
-//
-// some utility stuff
-//
-
-void dump_tag_bytes(stream* in)
- // Log the contents of the current tag, in hex.
-{
- static const int ROW_BYTES = 16;
- char row_buf[ROW_BYTES];
- int row_count = 0;
-
- while(in->get_position() < in->get_tag_end_position())
- {
- int c = in->read_u8();
- log_msg("%02X", c);
-
- if (c < 32) c = '.';
- if (c > 127) c = '.';
- row_buf[row_count] = c;
-
- row_count++;
- if (row_count >= ROW_BYTES)
- {
- log_msg(" ");
- for (int i = 0; i < ROW_BYTES; i++)
- {
- log_msg("%c", row_buf[i]);
- }
-
- log_msg("\n");
- row_count = 0;
- }
- else
- {
- log_msg(" ");
- }
- }
-
- if (row_count > 0)
- {
- log_msg("\n");
- }
-}
-
-
-//
-// progress callback stuff (from Vitaly)
-//
-progress_callback s_progress_function = NULL;
-
-// Host calls this to register a function for progress bar handling
-// during loading movies.
-void
-register_progress_callback(progress_callback progress_handle)
-{
- s_progress_function = progress_handle;
-}
-
-//
-// movie_def_impl
-//
-
-movie_def_impl::movie_def_impl(create_bitmaps_flag cbf,
- create_font_shapes_flag cfs)
- :
- _tag_loaders(s_tag_loaders), // FIXME: use a class-static
TagLoadersTable for movie_def_impl
- m_create_bitmaps(cbf),
- m_create_font_shapes(cfs),
- m_frame_rate(30.0f),
- m_frame_count(0u),
- m_version(0),
- m_loading_frame(0u),
- _loaded_bytes(0u),
- m_jpeg_in(0),
- _loader(*this)
-{
-}
-
-movie_def_impl::~movie_def_impl()
-{
- // Release our playlist data.
- {for (int i = 0, n = m_playlist.size(); i < n; i++)
- {
- for (int j = 0, m = m_playlist[i].size(); j < m; j++)
- {
- delete m_playlist[i][j];
- }
- }}
-
- // Release init action data.
- {for (size_t i = 0, n = m_init_action_list.size(); i < n; i++)
- {
- for (size_t j = 0, m = m_init_action_list[i].size(); j < m; j++)
- {
- delete m_init_action_list[i][j];
- }
- }}
-
- // It's supposed to be cleaned up in read()
- // TODO: join with loader thread instead ?
- //assert(m_jpeg_in.get() == NULL);
-}
-
-bool movie_def_impl::in_import_table(int character_id)
-{
- for (int i = 0, n = m_imports.size(); i < n; i++)
- {
- if (m_imports[i].m_character_id == character_id)
- {
- return true;
- }
- }
- return false;
-}
-
-void movie_def_impl::visit_imported_movies(import_visitor* visitor)
-{
- stringi_hash<bool> visited; // ugh!
-
- for (int i = 0, n = m_imports.size(); i < n; i++)
- {
- const import_info& inf = m_imports[i];
- if (visited.find(inf.m_source_url) == visited.end())
- {
- // Call back the visitor.
- visitor->visit(inf.m_source_url.c_str());
- visited[inf.m_source_url] = true;
- }
- }
-}
-
-void movie_def_impl::resolve_import(const char* source_url, movie_definition*
source_movie)
-{
- // @@ should be safe, but how can we verify
- // it? Compare a member function pointer, or
- // something?
- movie_def_impl* def_impl = static_cast<movie_def_impl*>(source_movie);
- movie_definition* def = static_cast<movie_definition*>(def_impl);
-
- // Iterate in reverse, since we remove stuff along the way.
- for (int i = m_imports.size() - 1; i >= 0; i--)
- {
- const import_info& inf = m_imports[i];
- if (inf.m_source_url == source_url)
- {
- // Do the import.
- smart_ptr<resource> res =
def->get_exported_resource(inf.m_symbol);
- bool imported = true;
-
- if (res == NULL)
- {
- log_error("import error: resource '%s' is not
exported from movie '%s'\n",
- inf.m_symbol.c_str(), source_url);
- }
- else if (font* f = res->cast_to_font())
- {
- // Add this shared font to our fonts.
- add_font(inf.m_character_id, f);
- imported = true;
- }
- else if (character_def* ch = res->cast_to_character_def())
- {
- // Add this character to our characters.
- add_character(inf.m_character_id, ch);
- imported = true;
- }
- else
- {
- log_error("import error: resource '%s' from movie
'%s' has unknown type\n",
- inf.m_symbol.c_str(), source_url);
- }
-
- if (imported)
- {
- m_imports.erase(m_imports.begin() + i);
-
- // Hold a ref, to keep this source
movie_definition alive.
- m_import_source_movies.push_back(source_movie);
- }
- }
- }
-}
-
-void movie_def_impl::add_character(int character_id, character_def* c)
-{
- assert(c);
- _dictionary.add_character(character_id, c);
-}
-
-character_def*
-movie_def_impl::get_character_def(int character_id)
-{
-#ifndef NDEBUG
- // make sure character_id is resolved
- if (in_import_table(character_id))
- {
- log_error("get_character_def(): character_id %d is still waiting
to be imported\n",
- character_id);
- }
-#endif // not NDEBUG
-
- smart_ptr<character_def> ch = _dictionary.get_character(character_id);
- assert(ch == NULL || ch->get_ref_count() > 1);
- return ch.get_ptr(); // mm... why don't we return the smart_ptr?
-}
-
-void movie_def_impl::add_font(int font_id, font* f)
-{
- assert(f);
- m_fonts.add(font_id, f);
-}
-
-font* movie_def_impl::get_font(int font_id)
-{
-#ifndef NDEBUG
- // make sure font_id is resolved
- if (in_import_table(font_id))
- {
- log_error("get_font(): font_id %d is still waiting to be
imported\n",
- font_id);
- }
-#endif // not NDEBUG
-
- smart_ptr<font> f;
- m_fonts.get(font_id, &f);
- assert(f == NULL || f->get_ref_count() > 1);
- return f.get_ptr();
-}
-
-bitmap_character_def* movie_def_impl::get_bitmap_character(int character_id)
-{
- smart_ptr<bitmap_character_def> ch;
- m_bitmap_characters.get(character_id, &ch);
- assert(ch == NULL || ch->get_ref_count() > 1);
- return ch.get_ptr();
-}
-
-void movie_def_impl::add_bitmap_character(int character_id,
bitmap_character_def* ch)
-{
- assert(ch);
- //log_msg("Add bitmap character %d", character_id);
- m_bitmap_characters.add(character_id, ch);
-
- add_bitmap_info(ch->get_bitmap_info());
-}
-
-sound_sample* movie_def_impl::get_sound_sample(int character_id)
-{
- smart_ptr<sound_sample> ch;
- m_sound_samples.get(character_id, &ch);
- assert(ch == NULL || ch->get_ref_count() > 1);
- return ch.get_ptr();
-}
-
-void movie_def_impl::add_sound_sample(int character_id, sound_sample* sam)
-{
- assert(sam);
- log_msg("Add sound sample %d", character_id);
- m_sound_samples.add(character_id, sam);
-}
-
-
-// Read a .SWF movie.
-bool
-movie_def_impl::read(tu_file* in, const std::string& url)
-{
-
- // we only read a movie once (well, headers at least)
- assert(_str.get() == NULL);
-
- if ( url == "" ) _url = "<anonymous>";
- else _url = url;
-
- uint32_t file_start_pos = in->get_position();
- uint32_t header = in->read_le32();
- m_file_length = in->read_le32();
- _swf_end_pos = file_start_pos + m_file_length;
-
- m_version = (header >> 24) & 255;
- if ((header & 0x0FFFFFF) != 0x00535746
- && (header & 0x0FFFFFF) != 0x00535743)
- {
- // ERROR
- log_error("gnash::movie_def_impl::read() -- "
- "file does not start with a SWF header!\n");
- return false;
- }
- bool compressed = (header & 255) == 'C';
-
- IF_VERBOSE_PARSE(
- log_parse("version = %d, file_length = %d",
- m_version, m_file_length);
- );
-
- tu_file* original_in = NULL;
- if (compressed)
- {
-#if TU_CONFIG_LINK_TO_ZLIB == 0
- log_error("movie_def_impl::read(): unable to read "
- "zipped SWF data; TU_CONFIG_LINK_TO_ZLIB is 0\n");
- return false;
-#endif
-
- IF_VERBOSE_PARSE(
- log_parse("file is compressed.");
- );
-
- original_in = in;
-
- // Uncompress the input as we read it.
- _zlib_file.reset(zlib_adapter::make_inflater(original_in));
- in = _zlib_file.get();
-
- // Subtract the size of the 8-byte header, since
- // it's not included in the compressed
- // stream length.
- _swf_end_pos = m_file_length - 8;
- }
-
- //stream str(in);
- _str.reset(new stream(in));
-
- m_frame_size.read(_str.get());
- m_frame_rate = _str->read_u16() / 256.0f;
- m_frame_count = _str->read_u16();
-
- // hack
- // Vitaly: I am not assured that it correctly
- m_frame_count = (m_frame_count == 0) ? 1 : m_frame_count;
-
- m_playlist.resize(m_frame_count);
- m_init_action_list.resize(m_frame_count);
-
- IF_VERBOSE_PARSE(
- m_frame_size.print();
- log_parse("frame rate = %f, frames = %d",
- m_frame_rate, m_frame_count);
- );
-
-#ifdef LOAD_MOVIES_IN_A_SEPARATE_THREAD
-
- // Start the loading frame
- if ( ! _loader.start() )
- {
- log_error("Could not start loading thread");
- }
-
- // Wait until 'startup_frames' have been loaded
-#if 1
- size_t startup_frames = 1;
-#else
- size_t startup_frames = m_frame_count;
-#endif
- ensure_frame_loaded(startup_frames);
-
-#else // undef LOAD_MOVIES_IN_A_SEPARATE_THREAD
-
- read_all_swf();
-#endif
-
-// Can't delete here as we will keep reading from it while playing
-// FIXME: remove this at end of reading (or in destructor)
-#if 0
- if (original_in)
- {
- // Done with the zlib_adapter.
- delete in;
- }
-#endif
-
- return true;
-}
-
-
-// 1-based frame number
-bool
-movie_def_impl::ensure_frame_loaded(size_t framenum)
-{
- //log_msg("Waiting for frame %u to be loaded", framenum);
- _loader.wait_for_frame(framenum);
- //log_msg("Condition reached (m_loading_frame=%u)", m_loading_frame);
-
-
- // TODO: return false on timeout
- return true;
-}
-
-
-/* movie_def_impl */
-void movie_def_impl::get_owned_fonts(std::vector<font*>* fonts)
- // Fill up *fonts with fonts that we own.
-{
- assert(fonts);
- fonts->resize(0);
-
- std::vector<int> font_ids;
-
- for (hash<int, smart_ptr<font> >::iterator it = m_fonts.begin();
- it != m_fonts.end();
- ++it)
- {
- font* f = it->second.get_ptr();
- if (f->get_owning_movie() == this)
- {
- // Sort by character id, so the ordering is
- // consistent for cache read/write.
- int id = it->first;
-
- // Insert in correct place.
- unsigned int insert;
- for (insert = 0; insert < font_ids.size(); insert++)
- {
- if (font_ids[insert] > id)
- {
- // We want to insert here.
- break;
- }
- }
- fonts->insert(fonts->begin() + insert, f);
- font_ids.insert(font_ids.begin() + insert, id);
- }
- }
-}
-
-
-/* movie_def_impl */
-void movie_def_impl::generate_font_bitmaps()
- // Generate bitmaps for our fonts, if necessary.
-{
- // Collect list of fonts.
- std::vector<font*> fonts;
- get_owned_fonts(&fonts);
- fontlib::generate_font_bitmaps(fonts, this);
-}
-
-void
-movie_def_impl::output_cached_data(tu_file* out, const cache_options& options)
-{
- // Write a little header.
- char header[5];
- strcpy(header, "gscX");
- header[3] = CACHE_FILE_VERSION;
- compiler_assert(CACHE_FILE_VERSION < 256);
-
- out->write_bytes(header, 4);
-
- // Write font data.
- std::vector<font*> fonts;
- get_owned_fonts(&fonts);
- fontlib::output_cached_data(out, fonts, this, options);
-
- // Write character data.
- {
-
- for ( CharacterDictionary::iterator
- it = _dictionary.begin(), itEnd = _dictionary.end();
- it != itEnd;
- ++it )
- {
- out->write_le16(it->first);
- it->second->output_cached_data(out, options);
- }
-
-#if 0
- for (hash<int, smart_ptr<character_def> >::iterator it =
m_characters.begin();
- it != m_characters.end();
- ++it)
- {
- out->write_le16(it->first);
- it->second->output_cached_data(out, options);
- }
-#endif
- }
-
- out->write_le16((int16_t) -1); // end of characters marker
-}
-
-
-void
-movie_def_impl::input_cached_data(tu_file* in)
-{
- // Read the header & check version.
- unsigned char header[4];
- in->read_bytes(header, 4);
- if (header[0] != 'g' || header[1] != 's' || header[2] != 'c')
- {
- log_error("cache file does not have the correct format;
skipping\n");
- return;
- }
- else if (header[3] != CACHE_FILE_VERSION)
- {
- log_error(
- "cached data is version %d, but we require version %d;
skipping\n",
- int(header[3]), CACHE_FILE_VERSION);
- return;
- }
-
- // Read the cached font data.
- std::vector<font*> fonts;
- get_owned_fonts(&fonts);
- fontlib::input_cached_data(in, fonts, this);
-
- // Read the cached character data.
- for (;;)
- {
- if (in->get_error() != TU_FILE_NO_ERROR)
- {
- log_error("error reading cache file (characters);
skipping\n");
- return;
- }
- if (in->get_eof())
- {
- log_error("unexpected eof reading cache file (characters);
skipping\n");
- return;
- }
-
- int16_t id = in->read_le16();
- if (id == (int16_t) -1) { break; } // done
-
- smart_ptr<character_def> ch = _dictionary.get_character(id);
- //m_characters.get(id, &ch);
- if (ch != NULL)
- {
- ch->input_cached_data(in);
- }
- else
- {
- log_error("sync error in cache file (reading characters)!
"
- "Skipping rest of cache data.\n");
- return;
- }
- }
-}
-
-movie_interface*
-movie_def_impl::create_instance()
-{
- movie_root* m = new movie_root(this);
- assert(m);
-
- sprite_instance* root_movie = new movie_instance(this, m, NULL);
- assert(root_movie);
-
- root_movie->set_name("_root");
- m->set_root_movie(root_movie);
-
- // @@ somewhere in here I *might* add _url variable
- // (or is it a member?)
-
- m->add_ref();
-
- root_movie->execute_frame_tags(0); // create _root dlist
-
- return m;
-}
-
-
-//
-// CharacterDictionary
-//
-
-void
-CharacterDictionary::dump_chars() const
-{
- for ( const_iterator it=begin(), endIt=end();
- it != endIt; ++it )
- {
- log_msg("Character %d @ %p", it->first, it->second.get_ptr());
- //character_def* cdef = it->second;
- }
-}
-
-smart_ptr<character_def>
-CharacterDictionary::get_character(int id)
-{
- container::iterator it = _map.find(id);
- if ( it == _map.end() )
- {
- log_msg("Could not find char %d, dump is:", id);
- dump_chars();
- return smart_ptr<character_def>();
- }
- else return it->second;
-}
-
-void
-CharacterDictionary::add_character(int id, smart_ptr<character_def> c)
-{
- //log_msg("CharacterDictionary: add char %d", id);
- _map[id] = c;
- //dump_chars();
-}
-
-// Load next chunk of this sprite frames.
-// This is possibly better defined in movie_definition
-void
-movie_def_impl::load_next_frame_chunk()
-{
-
- size_t framecount = get_frame_count();
- size_t lastloaded = get_loading_frame();
-
- // nothing to do
- if ( lastloaded == framecount ) return;
-
- size_t nextframe = lastloaded+1;
-
-#if FRAMELOAD_CHUNK
- nextframe += FRAMELOAD_CHUNK; // load in chunks of 10 frames
- if ( nextframe > framecount ) nextframe = framecount;
-#endif
- //log_msg("Framecount: %u, Lastloaded: %u", framecount, lastloaded);
- if ( nextframe <= framecount )
- {
-#ifdef DEBUG_FRAMES_LOAD // debugging
- log_msg("Ensure load of frame %u/%u (last loaded is: %u)",
- nextframe, framecount, lastloaded);
-#endif
- if ( ! ensure_frame_loaded(nextframe) )
- {
- log_error("Could not advance to frame %d!",
- nextframe);
- // these kind of errors should be handled by callers
- assert(0);
- }
- }
-#ifdef DEBUG_FRAMES_LOAD
- else
- {
- log_msg("No more frames to load. Framecount: %u, Lastloaded:
%u, next to load: %u", framecount, lastloaded, nextframe);
- }
-#endif
-}
-
-void
-movie_def_impl::read_all_swf()
-{
- assert(_str.get() != NULL);
-
- stream& str=*_str;
-
- //size_t it=0;
- while ( (uint32_t) str.get_position() < _swf_end_pos )
- {
- // Get exclusive lock on loader, to avoid
- // race conditions with wait_for_frame
- _loader.lock();
-
- //log_msg("Loading thread iteration %u", it++);
-
- SWF::tag_type tag_type = str.open_tag();
-
- if (s_progress_function != NULL)
- {
- s_progress_function((uint32_t)str.get_position(),
- _swf_end_pos);
- }
-
- SWF::TagLoadersTable::loader_function lf = NULL;
- //log_parse("tag_type = %d\n", tag_type);
- if (tag_type == SWF::SHOWFRAME)
- {
- // show frame tag -- advance to the next frame.
-
- IF_VERBOSE_PARSE(
- log_parse(" show_frame\n");
- );
-
- ++m_loading_frame;
-
- // signal load of frame
- _loader.signal_frame_loaded(m_loading_frame);
-
-#if DEBUG_FRAMES_LOAD
- log_msg("Loaded frame %u/%u",
- m_loading_frame, m_frame_count);
-#endif
- }
- else if (_tag_loaders.get(tag_type, &lf))
- {
- // call the tag loader. The tag loader should add
- // characters or tags to the movie data structure.
- (*lf)(&str, tag_type, this);
- }
- else
- {
- // no tag loader for this tag type.
- log_error("*** no tag loader for type %d
(movie)",
- tag_type);
- dump_tag_bytes(&str);
- }
-
- str.close_tag();
-
- if (tag_type == SWF::END)
- {
- if ((unsigned int) str.get_position() != _swf_end_pos)
- {
- // Safety break, so we don't read past
- // the end of the movie.
- log_warning("hit stream-end tag, "
- "but not at the advertised SWF end; "
- "stopping for safety.");
- _loader.unlock();
- break;
- }
- }
- _loader.unlock();
-
- }
-
-}
-
-} // namespace gnash
-
Index: server/movie_def_impl.h
===================================================================
RCS file: server/movie_def_impl.h
diff -N server/movie_def_impl.h
--- server/movie_def_impl.h 22 Aug 2006 00:53:54 -0000 1.22
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,570 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-
-#ifndef GNASH_MOVIE_DEF_IMPL_H
-#define GNASH_MOVIE_DEF_IMPL_H
-
-#include "container.h"
-#include "smart_ptr.h"
-#include "button.h" // for mouse_button_state
-#include "timers.h" // for Timer
-#include "fontlib.h"
-#include "font.h"
-#include "jpeg.h"
-#include "tu_file.h"
-#include "movie_definition.h" // for inheritance
-#include "character_def.h" // for smart_ptr visibility of dtor
-#include "bitmap_character_def.h" // for smart_ptr visibility of dtor
-#include "resource.h" // for smart_ptr visibility of dtor
-#include "stream.h" // for get_bytes_loaded
-
-#include <map> // for CharacterDictionary
-#include <string>
-#include <memory> // for auto_ptr
-
-// We'd avoid SDL threads if possible. Please define the macro below
-// if you experience problems and report the difference on gnash-dev
-#undef REALLY_USE_SDL_THREADS
-
-#ifdef REALLY_USE_SDL_THREADS
-#ifdef HAVE_SDL_H
-# define USE_SDL_THREADS 1
-#endif
-#endif
-
-#ifdef USE_SDL_THREADS
-# include "SDL.h"
-# include "SDL_thread.h"
-#endif
-
-
-namespace gnash
-{
-
-// Forward declarations
-class import_info;
-class movie_def_impl;
-class movie_root;
-
-//
-// Helper for movie_def_impl
-//
-
-class import_info
-{
- friend class movie_def_impl;
-
- tu_string m_source_url;
- int m_character_id;
- tu_string m_symbol;
-
- import_info()
- :
- m_character_id(-1)
- {
- }
-
- import_info(const char* source, int id, const char* symbol)
- :
- m_source_url(source),
- m_character_id(id),
- m_symbol(symbol)
- {
- }
-};
-
-/// \brief
-/// movie_def_impl helper class handling start and execution of
-/// an SWF loading thread
-///
-class MovieLoader
-{
-
-public:
-
- MovieLoader(movie_def_impl& md);
-
- ~MovieLoader();
-
- /// Start loading thread.
- //
- /// The associated movie_def_impl instance
- /// is expected to have already read the SWF
- /// header and applied a zlib adapter if needed.
- ///
- bool start();
-
- /// Wait for specified frame number (1-based) to be loaded
- //
- /// Block caller thread until frame is loaded.
- ///
- void wait_for_frame(size_t framenum);
-
- /// Signal load of given frame number (if anyone waiting for it)
- void signal_frame_loaded(size_t frameno);
-
- void lock();
-
- void unlock();
-
-private:
-
- size_t _waiting_for_frame;
- movie_def_impl& _movie_def;
-
-#ifdef USE_SDL_THREADS
-
- static int execute(void* arg);
-
- SDL_Thread* _thread;
- SDL_cond* _frame_reached_condition;
- SDL_mutex* _mutex;
-
-#else
-
- pthread_cond_t _frame_reached_condition;
- pthread_mutex_t _mutex;
- pthread_t _thread;
-
- /// Entry point for the actual thread
- static void *execute(void* arg);
-
-#endif
-
-};
-
-/// The Characters dictionary associated with each SWF file.
-//
-/// This is a set of Characters defined by define tags and
-/// getting assigned a unique ID.
-///
-class CharacterDictionary
-{
-
-public:
-
- /// The container used by this dictionary
- //
- /// It contains pairs of 'int' and 'smart_ptr<character_def>'
- ///
- typedef std::map< int, smart_ptr<character_def> > container;
- //typedef hash< int, smart_ptr<character_def> >container;
-
- typedef container::iterator iterator;
-
- typedef container::const_iterator const_iterator;
-
- /// Get the Character with the given id
- //
- /// returns a NULL if the id is unknown.
- ///
- smart_ptr<character_def> get_character(int id);
-
- /// Add a Character assigning it the given id
- //
- /// replaces any existing character with the same id
- ///
- void add_character(int id, smart_ptr<character_def> c);
-
- /// Return an iterator to the first dictionary element
- iterator begin() { return _map.begin(); }
-
- /// Return a const_iterator to the first dictionary element
- const_iterator begin() const { return _map.begin(); }
-
- /// Return an iterator to one-past last dictionary element
- iterator end() { return _map.end(); }
-
- /// Return a const_iterator to one-past last dictionary element
- const_iterator end() const { return _map.end(); }
-
- /// Dump content of the dictionary (debugging only)
- void dump_chars(void) const;
-private:
-
- container _map;
-
-};
-
-
-/// Immutable definition of a movie's contents.
-//
-/// It cannot be played directly, and does not hold
-/// current state; for that you need to call create_instance()
-/// to get a movie instance (gnash::movie_interface).
-///
-class movie_def_impl : public movie_definition
-{
- /// Characters Dictionary
- CharacterDictionary _dictionary;
- //hash<int, smart_ptr<character_def> > m_characters;
-
- /// Tags loader table
- SWF::TagLoadersTable& _tag_loaders;
-
- hash<int, smart_ptr<font> > m_fonts;
- hash<int, smart_ptr<bitmap_character_def> > m_bitmap_characters;
- hash<int, smart_ptr<sound_sample> > m_sound_samples;
- hash<int, smart_ptr<sound_sample> > m_sound_streams;
-
- /// A list of movie control events for each frame.
- std::vector<std::vector<execute_tag*> > m_playlist;
-
- /// Init actions for each frame.
- std::vector<std::vector<execute_tag*> > m_init_action_list;
-
- /// 0-based frame #'s
- stringi_hash<size_t> m_named_frames;
-
- stringi_hash<smart_ptr<resource> > m_exports;
-
- /// Items we import.
- std::vector<import_info> m_imports;
-
- /// Movies we import from; hold a ref on these,
- /// to keep them alive
- std::vector<smart_ptr<movie_definition> > m_import_source_movies;
-
- /// Bitmaps used in this movie; collected in one place to make
- /// it possible for the host to manage them as textures.
- std::vector<smart_ptr<bitmap_info> > m_bitmap_list;
-
- create_bitmaps_flag m_create_bitmaps;
- create_font_shapes_flag m_create_font_shapes;
-
- rect m_frame_size;
- float m_frame_rate;
- size_t m_frame_count;
- int m_version;
- size_t m_loading_frame;
- int m_loading_sound_stream;
- uint32 m_file_length;
- size_t _loaded_bytes;
-
- std::auto_ptr<jpeg::input> m_jpeg_in;
-
- std::string _url;
-
- std::auto_ptr<stream> _str;
-
- tu_file* in;
-
- std::auto_ptr<tu_file> _zlib_file;
-
- /// swf end position (as read from header)
- unsigned int _swf_end_pos;
-
- /// asyncronous SWF loader and parser
- MovieLoader _loader;
-
-public:
-
- movie_def_impl(create_bitmaps_flag cbf, create_font_shapes_flag cfs);
-
- ~movie_def_impl();
-
- // ...
- size_t get_frame_count() const { return m_frame_count; }
- float get_frame_rate() const { return m_frame_rate; }
- const rect& get_frame_size() const { return m_frame_size; }
-
- float get_width_pixels() const
- {
- return ceilf(TWIPS_TO_PIXELS(m_frame_size.width()));
- }
-
- float get_height_pixels() const
- {
- return ceilf(TWIPS_TO_PIXELS(m_frame_size.height()));
- }
-
- virtual int get_version() const { return m_version; }
-
- virtual size_t get_loading_frame() const
- {
- return m_loading_frame;
- }
-
-#if 0 // renamed to get_bytes_total
- uint32 get_file_bytes() const {
- return m_file_length;
- }
-#endif
-
- /// Get number of bytes loaded from input stream
- size_t get_bytes_loaded() const {
-#if 0 // temporarly disabled because broken
- uint32 ret = _loaded_bytes;
-#else
- uint32 ret = m_file_length;
-#endif
- log_msg("get_bytes_loaded returning %u (loaded frame: %zu/%zu)",
- ret, m_loading_frame, m_frame_count);
- return ret;
- }
-
- /// Get total number of bytes in input stream
- size_t get_bytes_total() const {
- log_msg("get_bytes_total returning %u", m_file_length);
- return m_file_length;
- }
-
- /// Returns DO_CREATE_BITMAPS if we're supposed to
- /// initialize our bitmap infos, or DO_NOT_INIT_BITMAPS
- /// if we're supposed to create blank placeholder
- /// bitmaps (to be init'd later explicitly by the host
- /// program).
- virtual create_bitmaps_flag get_create_bitmaps() const
- {
- return m_create_bitmaps;
- }
-
- /// Returns DO_LOAD_FONT_SHAPES if we're supposed to
- /// initialize our font shape info, or
- /// DO_NOT_LOAD_FONT_SHAPES if we're supposed to not
- /// create any (vector) font glyph shapes, and instead
- /// rely on precached textured fonts glyphs.
- virtual create_font_shapes_flag get_create_font_shapes() const
- {
- return m_create_font_shapes;
- }
-
- /// All bitmap_info's used by this movie should be
- /// registered with this API.
- virtual void add_bitmap_info(bitmap_info* bi)
- {
- m_bitmap_list.push_back(bi);
- }
-
- virtual int get_bitmap_info_count() const
- {
- return m_bitmap_list.size();
- }
-
- virtual bitmap_info* get_bitmap_info(int i) const
- {
- return m_bitmap_list[i].get_ptr();
- }
-
- /// Expose one of our resources under the given symbol,
- /// for export. Other movies can import it.
- virtual void export_resource(const tu_string& symbol,
- resource* res)
- {
- // SWF sometimes exports the same thing more than once!
- m_exports[symbol] = res;
- }
-
- /// Get the named exported resource, if we expose it.
- /// Otherwise return NULL.
- virtual smart_ptr<resource> get_exported_resource(const tu_string&
symbol)
- {
- smart_ptr<resource> res;
- m_exports.get(symbol, &res);
- return res;
- }
-
- /// Adds an entry to a table of resources that need to
- /// be imported from other movies. Client code must
- /// call resolve_import() later, when the source movie
- /// has been loaded, so that the actual resource can be
- /// used.
- virtual void add_import(const char* source_url, int id, const char*
symbol)
- {
- assert(in_import_table(id) == false);
-
- m_imports.push_back(import_info(source_url, id, symbol));
- }
-
- /// Debug helper; returns true if the given
- /// character_id is listed in the import table.
- bool in_import_table(int character_id);
-
- /// Calls back the visitor for each movie that we
- /// import symbols from.
- virtual void visit_imported_movies(import_visitor* visitor);
-
- /// Grabs the stuff we want from the source movie.
- virtual void resolve_import(const char* source_url,
- movie_definition* source_movie);
-
- void add_character(int character_id, character_def* c);
-
- /// \brief
- /// Return a character from the dictionary
- /// NOTE: call add_ref() on the return or put in a smart_ptr<>
- /// TODO: return a smart_ptr<> directly...
- ///
- character_def* get_character_def(int character_id);
-
- /// Returns 0-based frame #
- bool get_labeled_frame(const char* label, size_t* frame_number)
- {
- return m_named_frames.get(label, frame_number);
- }
-
- void add_font(int font_id, font* f);
- font* get_font(int font_id);
- bitmap_character_def* get_bitmap_character(int character_id);
- void add_bitmap_character(int character_id, bitmap_character_def*
ch);
- sound_sample* get_sound_sample(int character_id);
- virtual void add_sound_sample(int character_id, sound_sample* sam);
- virtual void set_loading_sound_stream_id(int id) {
m_loading_sound_stream = id; }
- int get_loading_sound_stream_id() { return
m_loading_sound_stream; }
-
- /// Add an execute_tag to this movie_definition's playlist
- void add_execute_tag(execute_tag* e)
- {
- assert(e);
- m_playlist[m_loading_frame].push_back(e);
- }
-
- /// Need to execute the given tag before entering the
- /// currently-loading frame for the first time.
- ///
- /// @@ AFAIK, the sprite_id is totally pointless -- correct?
- //void add_init_action(int sprite_id, execute_tag* e)
- void add_init_action(execute_tag* e)
- {
- assert(e);
- m_init_action_list[m_loading_frame].push_back(e);
- }
-
- /// Labels the frame currently being loaded with the
- /// given name. A copy of the name string is made and
- /// kept in this object.
- void add_frame_name(const char* name)
- {
- assert(m_loading_frame < m_frame_count);
-
- tu_string n = name;
-
- if (m_named_frames.get(n, NULL) == false) //
frame should not already have a name (?)
- {
- m_named_frames.add(n, m_loading_frame); // stores
0-based frame #
- }
- }
-
- /// Set an input object for later loading DefineBits
- /// images (JPEG images without the table info).
- void set_jpeg_loader(std::auto_ptr<jpeg::input> j_in)
- {
- assert(m_jpeg_in.get() == NULL);
- m_jpeg_in = j_in;
- }
-
- /// Get the jpeg input loader, to load a DefineBits
- /// image (one without table info).
- //
- /// NOTE: ownership is NOT transferred
- ///
- jpeg::input* get_jpeg_loader()
- {
- return m_jpeg_in.get();
- }
-
- virtual const std::vector<execute_tag*>& get_playlist(size_t
frame_number)
- {
- return m_playlist[frame_number];
- }
-
- virtual const std::vector<execute_tag*>* get_init_actions(size_t
frame_number)
- {
- assert(frame_number <= m_loading_frame);
- //ensure_frame_loaded(frame_number);
- return &m_init_action_list[frame_number];
- }
-
- /// Read (w/out playing) a Movie definition from an SWF file.
- //
- /// Note that the *full* SWF is read before
- /// this function returns. We should change this
- /// interface to both read and play a file instead.
- ///
- /// This function uses a private TagLoadersTable
- /// to interpret specific tag types.
- /// Currently the TagLoadersTable in use is the
- /// gnash::s_tag_loaders global variable
- ///
- /// @param in the tu_file from which to read SWF
- /// @param url the url associated with the input
- /// @return false if SWF file could not be parsed
- ///
- bool read(tu_file *in, const std::string& url);
-
- /// \brief
- /// Ensure that frame number 'framenum' (1-based offset)
- /// has been loaded (load on demand).
- ///
- bool ensure_frame_loaded(size_t framenum);
-
- /// Read and parse all the SWF stream (blocking until load is finished)
- void read_all_swf();
-
- virtual void load_next_frame_chunk();
-
- /// Fill up *fonts with fonts that we own.
- void get_owned_fonts(std::vector<font*>* fonts);
-
- /// Generate bitmaps for our fonts, if necessary.
- void generate_font_bitmaps();
-
- /// Dump our cached data into the given stream.
- void output_cached_data(tu_file* out,
- const cache_options& options);
-
- /// \brief
- /// Read in cached data and use it to prime our
- /// loaded characters.
- void input_cached_data(tu_file* in);
-
- /// \brief
- /// Create a playable movie_root instance from a def.
- //
- /// The _root reference of the newly created instance
- /// will be set to a newly created sprite_instace (Help!)
- ///
- movie_interface* create_instance();
-
- virtual const std::string& get_url() const { return _url; }
-
-
-};
-
-} // namespace gnash
-
-#endif // GNASH_MOVIE_DEF_IMPL_H
Index: server/movie_definition.h
===================================================================
RCS file: server/movie_definition.h
diff -N server/movie_definition.h
--- server/movie_definition.h 14 Aug 2006 23:16:57 -0000 1.11
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,269 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-
-
-/// \page movie SWF Movies
-///
-/// SWF Movies definitions are created by reading an SWF stream.
-/// Gnash doesn't play SWF Movie definitions, but instances.
-/// So you can play the same SWF file (Movie definiton) using
-/// multiple instances.
-///
-/// A Movie definition is defined by the gnash::movie_definition class.
-/// A Movie instance is defined by the gnash::movie_interface class.
-///
-/// A Movie instance exposes the ActionScript
-/// Object base interface (gnash::as_object),
-/// thus it can manage gnash::as_value members.
-///
-/// The implementation of SWF parsing for a Movie definition
-/// is found in gnash::movie_def_impl::read.
-/// Note that movie_definition is also used as a base class
-/// to sprite_definition, which is a sub-movie defined in an SWF
-/// file. This seems to be the only reason to have a
-/// movie_def_impl class, being the top-level definition of
-/// a movie (the one with a CharacterDictionary in it).
-///
-
-
-#ifndef GNASH_MOVIE_DEFINITION_H
-#define GNASH_MOVIE_DEFINITION_H
-
-#include "container.h"
-#include "button.h" // for mouse_button_state
-#include "timers.h" // for Timer
-#include "fontlib.h"
-#include "font.h"
-#include "jpeg.h"
-#include "tu_file.h"
-
-#include <string>
-#include <memory> // for auto_ptr
-
-namespace gnash
-{
-
-/// Client program's interface to the definition of a movie
-//
-/// (i.e. the shared constant source info).
-///
-struct movie_definition : public character_def
-{
- virtual int get_version() const = 0;
- virtual float get_width_pixels() const = 0;
- virtual float get_height_pixels() const = 0;
- virtual size_t get_frame_count() const = 0;
- virtual float get_frame_rate() const = 0;
-
- virtual size_t get_bytes_loaded() const = 0;
- virtual size_t get_bytes_total() const = 0;
-
- /// Create a playable movie instance from a def.
- //
- /// This calls add_ref() on the movie_interface internally.
- /// Call drop_ref() on the movie_interface when you're done with it.
- /// Or use smart_ptr<T> from base/smart_ptr.h if you want.
- ///
- virtual movie_interface* create_instance() = 0;
-
- virtual void output_cached_data(tu_file* out, const cache_options&
options) = 0;
- virtual void input_cached_data(tu_file* in) = 0;
-
- /// \brief
- /// Causes this movie def to generate texture-mapped
- /// versions of all the fonts it owns.
- //
- /// This improves
- /// speed and quality of text rendering. The
- /// texture-map data is serialized in the
- /// output/input_cached_data() calls, so you can
- /// preprocess this if you load cached data.
- ///
- virtual void generate_font_bitmaps() = 0;
-
- //
- // (optional) API to support gnash::create_movie_no_recurse().
- //
-
- /// \brief
- /// Call visit_imported_movies() to retrieve a list of
- /// names of movies imported into this movie.
- //
- /// visitor->visit() will be called back with the name
- /// of each imported movie.
- struct import_visitor
- {
- virtual ~import_visitor() {}
- virtual void visit(const char* imported_movie_filename) = 0;
- };
- virtual void visit_imported_movies(import_visitor* visitor) = 0;
-
- /// Call this to resolve an import of the given movie.
- /// Replaces the dummy placeholder with the real
- /// movie_definition* given.
- virtual void resolve_import(const char* name, movie_definition* def)
= 0;
-
- //
- // (optional) API to support host-driven creation of textures.
- //
- // Create the movie using gnash::create_movie_no_recurse(...,
DO_NOT_LOAD_BITMAPS),
- // and then initialize each bitmap info via get_bitmap_info_count(),
get_bitmap_info(),
- // and bitmap_info::init_*_image() or your own subclassed API.
- //
- // E.g.:
- //
- // // During preprocessing:
- // // This will create bitmap_info's using the rgba, rgb, alpha
contructors.
- // my_def = gnash::create_movie_no_recurse("myfile.swf",
DO_LOAD_BITMAPS);
- // int ct = my_def->get_bitmap_info_count();
- // for (int i = 0; i < ct; i++)
- // {
- // my_bitmap_info_subclass* bi = NULL;
- // my_def->get_bitmap_info(i, (bitmap_info**) &bi);
- //
my_precomputed_textures.push_back(bi->m_my_internal_texture_reference);
- // }
- // // Save out my internal data.
- // my_precomputed_textures->write_into_some_cache_stream(...);
- //
- // // Later, during run-time loading:
- // my_precomputed_textures->read_from_some_cache_stream(...);
- // // This will create blank bitmap_info's.
- // my_def = gnash::create_movie_no_recurse("myfile.swf",
DO_NOT_LOAD_BITMAPS);
- //
- // // Push cached texture info into the movie's bitmap_info structs.
- // int ct = my_def->get_bitmap_info_count();
- // for (int i = 0; i < ct; i++)
- // {
- // my_bitmap_info_subclass* bi = (my_bitmap_info_subclass*)
my_def->get_bitmap_info(i);
- // bi->set_internal_texture_reference(my_precomputed_textures[i]);
- // }
- virtual int get_bitmap_info_count() const = 0;
- virtual bitmap_info* get_bitmap_info(int i) const = 0;
-
- // From movie_definition_sub
-
- virtual const std::vector<execute_tag*>& get_playlist(size_t
frame_number) = 0;
- virtual const std::vector<execute_tag*>* get_init_actions(size_t
frame_number) = 0;
- virtual smart_ptr<resource> get_exported_resource(const tu_string&
symbol) = 0;
-
-
- /// \brief
- /// Get a character from the dictionary.
- ///
- /// Note that only top-level movies (those belonging to a single
- /// SWF stream) have a characters dictionary, thus our
- /// movie_def_impl. The other derived class, sprite_definition
- /// will seek for characters in it's base movie_def_impl.
- ///
- virtual character_def* get_character_def(int id) = 0;
-
- virtual bool get_labeled_frame(const char* label, size_t* frame_number)
= 0;
-
- //
- // For use during creation.
- //
-
- /// Returns 1 based index. Ex: if 1 then 1st frame as been fully loaded
- virtual size_t get_loading_frame() const = 0;
-
- virtual void add_character(int id, character_def* ch) = 0;
-
- virtual void add_font(int id, font* ch) = 0;
-
- virtual font* get_font(int id) = 0;
-
- virtual void add_execute_tag(execute_tag* c) = 0;
-
- // sprite_id was useless
- //virtual void add_init_action(int sprite_id, execute_tag* c) = 0;
- virtual void add_init_action(execute_tag* c) = 0;
-
- virtual void add_frame_name(const char* name) = 0;
-
- virtual void set_jpeg_loader(std::auto_ptr<jpeg::input> j_in) = 0;
-
- virtual jpeg::input* get_jpeg_loader() = 0;
-
- virtual bitmap_character_def* get_bitmap_character(int character_id)=0;
-
- virtual void add_bitmap_character(int character_id,
- bitmap_character_def* ch) = 0;
-
- virtual sound_sample* get_sound_sample(int character_id) = 0;
-
- virtual void add_sound_sample(int character_id, sound_sample* sam) = 0;
-
- virtual void set_loading_sound_stream_id(int id) = 0;
-
- virtual int get_loading_sound_stream_id() = 0;
-
-
- virtual void export_resource(const tu_string& symbol,
- resource* res) = 0;
-
- virtual void add_import(const char* source_url, int id,
- const char* symbol_name) = 0;
-
- virtual void add_bitmap_info(bitmap_info* ch) = 0;
-
- // ...
-
- virtual create_bitmaps_flag get_create_bitmaps() const = 0;
- virtual create_font_shapes_flag get_create_font_shapes() const = 0;
-
- /// \brief
- /// Return the URL of the SWF stream this definition has been read
- /// from.
- virtual const std::string& get_url() const = 0;
-
- /// \brief
- /// Ensure that frame number 'framenum' (1-based offset)
- /// has been loaded (load on demand).
- //
- /// @return false on error (like not enough frames available).
- ///
- virtual bool ensure_frame_loaded(size_t framenum) = 0;
-
- /// \brief
- /// Load next chunk of this movie/sprite frames if available.
- ///
- virtual void load_next_frame_chunk() = 0;
-};
-
-} // namespace gnash
-
-#endif // GNASH_MOVIE_DEFINITION_H
Index: server/shape_character_def.cpp
===================================================================
RCS file: server/shape_character_def.cpp
diff -N server/shape_character_def.cpp
--- server/shape_character_def.cpp 13 Aug 2006 16:45:11 -0000 1.7
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,718 +0,0 @@
-// shape.cpp -- Thatcher Ulrich <address@hidden> 2003
-
-// This source code has been donated to the Public Domain. Do
-// whatever you want with it.
-
-// Quadratic bezier outline shapes, the basis for most SWF rendering.
-
-
-#include "shape_character_def.h"
-#include "shape.h" // for mesh_set
-
-#include "impl.h"
-#include "log.h"
-#include "render.h"
-#include "stream.h"
-#include "tesselate.h"
-#include "movie_definition.h" // TODO: check if really needed
-//#include "bitmap_character_def.h"
-#include "sprite_instance.h"
-
-#include "tu_file.h"
-
-#include <float.h>
-
-
-#define DEBUG_DISPLAY_SHAPE_PATHS
-#ifdef DEBUG_DISPLAY_SHAPE_PATHS
-// For debugging only!
-bool gnash_debug_show_paths = false;
-#endif // DEBUG_DISPLAY_SHAPE_PATHS
-
-
-namespace gnash {
-
-static float s_curve_max_pixel_error = 1.0f;
-
-
-//
-// helper functions.
-//
-
-void set_curve_max_pixel_error(float pixel_error)
-{
- s_curve_max_pixel_error = fclamp(pixel_error, 1e-6f, 1e6f);
-}
-
-float get_curve_max_pixel_error()
-{
- return s_curve_max_pixel_error;
-}
-
-
-// Read fill styles, and push them onto the given style array.
-static void
-read_fill_styles(std::vector<fill_style>& styles, stream* in,
- int tag_type, movie_definition* m)
-{
- //assert(styles);
-
- // Get the count.
- int fill_style_count = in->read_u8();
- if (tag_type > 2) {
- if (fill_style_count == 0xFF)
- {
- fill_style_count = in->read_u16();
- }
- }
-
- IF_VERBOSE_PARSE (
- log_parse(" read_fill_styles: count = %d", fill_style_count);
- );
-
- // Read the styles.
- for (int i = 0; i < fill_style_count; i++) {
- styles.resize(styles.size() + 1);
- //styles[styles.size() - 1].read(in, tag_type, m);
- styles.back().read(in, tag_type, m);
- }
-}
-
-
-static void
-read_line_styles(std::vector<line_style>& styles, stream* in, int tag_type)
- // Read line styles and push them onto the back of the given array.
-{
- // Get the count.
- int line_style_count = in->read_u8();
-
- IF_VERBOSE_PARSE
- (
- log_parse(" read_line_styles: count = %d", line_style_count);
- );
-
- // @@ does the 0xFF flag apply to all tag types?
- // if (tag_type > 2)
- // {
- if (line_style_count == 0xFF) {
- line_style_count = in->read_u16();
- IF_VERBOSE_PARSE
- (
- log_parse(" read_line_styles: count2 = %d", line_style_count);
- );
- }
- // }
-
- // Read the styles.
- for (int i = 0; i < line_style_count; i++) {
- styles.resize(styles.size() + 1);
- //styles[styles.size() - 1].read(in, tag_type);
- styles.back().read(in, tag_type);
- }
-}
-
-
-shape_character_def::shape_character_def()
-{
-}
-
-
-shape_character_def::~shape_character_def()
-{
- // Free our mesh_sets.
- for (unsigned int i = 0; i < m_cached_meshes.size(); i++) {
- delete m_cached_meshes[i];
- }
-}
-
-
-void
-shape_character_def::read(stream* in, int tag_type, bool with_style,
- movie_definition* m)
-{
- if (with_style) {
- m_bound.read(in);
- read_fill_styles(m_fill_styles, in, tag_type, m);
- read_line_styles(m_line_styles, in, tag_type);
- }
-
- int num_fill_bits = in->read_uint(4);
- int num_line_bits = in->read_uint(4);
-
- IF_VERBOSE_PARSE
- (
- log_parse(" shape_character_def read: nfillbits = %d, nlinebits = %d",
num_fill_bits, num_line_bits);
- );
-
- // These are state variables that keep the
- // current position & style of the shape
- // outline, and vary as we read the edge data.
- //
- // At the moment we just store each edge with
- // the full necessary info to render it, which
- // is simple but not optimally efficient.
- int fill_base = 0;
- int line_base = 0;
- float x = 0, y = 0;
- path current_path;
-
-#define SHAPE_LOG 0
- // SHAPERECORDS
- for (;;) {
- int type_flag = in->read_uint(1);
- if (type_flag == 0) {
- // Parse the record.
- int flags = in->read_uint(5);
- if (flags == 0) {
- // End of shape records.
-
- // Store the current path if any.
- if (! current_path.is_empty())
- {
- m_paths.push_back(current_path);
- current_path.m_edges.resize(0);
- }
-
- break;
- }
- if (flags & 0x01) {
- // move_to = 1;
-
- // Store the current path if any, and prepare a fresh one.
- if (! current_path.is_empty()) {
- m_paths.push_back(current_path);
- current_path.m_edges.resize(0);
- }
-
- int num_move_bits = in->read_uint(5);
- int move_x = in->read_sint(num_move_bits);
- int move_y = in->read_sint(num_move_bits);
-
- x = (float) move_x;
- y = (float) move_y;
-
- // Set the beginning of the path.
- current_path.m_ax = x;
- current_path.m_ay = y;
-
- IF_VERBOSE_PARSE
- (
- if (SHAPE_LOG)
- log_parse(" shape_character read: moveto %4g %4g", x, y);
- );
- }
- if ((flags & 0x02) && num_fill_bits > 0) {
- // fill_style_0_change = 1;
- if (! current_path.is_empty()) {
- m_paths.push_back(current_path);
- current_path.m_edges.resize(0);
- current_path.m_ax = x;
- current_path.m_ay = y;
- }
- int style = in->read_uint(num_fill_bits);
- if (style > 0) {
- style += fill_base;
- }
- current_path.m_fill0 = style;
- IF_VERBOSE_PARSE
- (
- if (SHAPE_LOG) {
- log_parse(" shape_character read: fill0 = %d",
current_path.m_fill0);
- }
- );
-
- }
- if ((flags & 0x04) && num_fill_bits > 0) {
- // fill_style_1_change = 1;
- if (! current_path.is_empty()) {
- m_paths.push_back(current_path);
- current_path.m_edges.resize(0);
- current_path.m_ax = x;
- current_path.m_ay = y;
- }
- int style = in->read_uint(num_fill_bits);
- if (style > 0) {
- style += fill_base;
- }
- current_path.m_fill1 = style;
- IF_VERBOSE_PARSE (
- if (SHAPE_LOG) {
- log_parse(" shape_character read: fill1 = %d",
current_path.m_fill1);
- }
- );
- }
- if ((flags & 0x08) && num_line_bits > 0) {
- // line_style_change = 1;
- if (! current_path.is_empty()) {
- m_paths.push_back(current_path);
- current_path.m_edges.resize(0);
- current_path.m_ax = x;
- current_path.m_ay = y;
- }
- int style = in->read_uint(num_line_bits);
- if (style > 0) {
- style += line_base;
- }
- current_path.m_line = style;
- IF_VERBOSE_PARSE (
- if (SHAPE_LOG)
- {
- log_parse(" shape_character_read: line = %d",
current_path.m_line);
- }
- );
- }
- if (flags & 0x10) {
- if (tag_type == 2) {
- tag_type+=20;
- }
- assert(tag_type >= 22);
-
- IF_VERBOSE_PARSE (
- log_parse(" shape_character read: more fill styles");
- );
-
- // Store the current path if any.
- if (! current_path.is_empty()) {
- m_paths.push_back(current_path);
- current_path.m_edges.resize(0);
-
- // Clear styles.
- current_path.m_fill0 = -1;
- current_path.m_fill1 = -1;
- current_path.m_line = -1;
- }
- // Tack on an empty path signalling a new shape.
- // @@ need better understanding of whether this is correct??!?!!
- // @@ i.e., we should just start a whole new shape here, right?
- m_paths.push_back(path());
- m_paths.back().m_new_shape = true;
-
- fill_base = m_fill_styles.size();
- line_base = m_line_styles.size();
- read_fill_styles(m_fill_styles, in, tag_type, m);
- read_line_styles(m_line_styles, in, tag_type);
- num_fill_bits = in->read_uint(4);
- num_line_bits = in->read_uint(4);
- }
- } else {
- // EDGERECORD
- int edge_flag = in->read_uint(1);
- if (edge_flag == 0) {
- // curved edge
- int num_bits = 2 + in->read_uint(4);
- float cx = x + in->read_sint(num_bits);
- float cy = y + in->read_sint(num_bits);
- float ax = cx + in->read_sint(num_bits);
- float ay = cy + in->read_sint(num_bits);
-
- IF_VERBOSE_PARSE (
- if (SHAPE_LOG)
- {
- log_parse(" shape_character read: curved edge = %4g %4g
- %4g %4g - %4g %4g", x, y, cx, cy, ax, ay);
- }
- );
-
- current_path.m_edges.push_back(edge(cx, cy, ax, ay));
-
- x = ax;
- y = ay;
- } else {
- // straight edge
- int num_bits = 2 + in->read_uint(4);
- int line_flag = in->read_uint(1);
- float dx = 0, dy = 0;
- if (line_flag) {
- // General line.
- dx = (float) in->read_sint(num_bits);
- dy = (float) in->read_sint(num_bits);
- } else {
- int vert_flag = in->read_uint(1);
- if (vert_flag == 0) {
- // Horizontal line.
- dx = (float) in->read_sint(num_bits);
- } else {
- // Vertical line.
- dy = (float) in->read_sint(num_bits);
- }
- }
-
- IF_VERBOSE_PARSE (
- if (SHAPE_LOG)
- {
- log_parse(" shape_character_read: straight edge = %4g %4g
- %4g %4g", x, y, x + dx, y + dy);
- }
- );
-
- current_path.m_edges.push_back(edge(x + dx, y + dy, x + dx, y +
dy));
-
- x += dx;
- y += dy;
- }
- }
- }
-}
-
-
-void shape_character_def::display(character* inst)
- // Draw the shape using our own inherent styles.
-{
-// GNASH_REPORT_FUNCTION;
-
- matrix mat = inst->get_world_matrix();
- cxform cx = inst->get_world_cxform();
-
- float pixel_scale = inst->get_parent()->get_pixel_scale();
- display(mat, cx, pixel_scale, m_fill_styles, m_line_styles);
-}
-
-
-#ifdef DEBUG_DISPLAY_SHAPE_PATHS
-
-#include "ogl.h"
-
-
-static void point_normalize(point* p)
-{
- float mag2 = p->m_x * p->m_x + p->m_y * p->m_y;
- if (mag2 < 1e-9f) {
- // Very short vector.
- // @@ log error
-
- // Arbitrary unit vector.
- p->m_x = 1;
- p->m_y = 0;
- }
-
- float inv_mag = 1.0f / sqrtf(mag2);
- p->m_x *= inv_mag;
- p->m_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.m_x;
- float y = p.m_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 matrix& 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++) {
-// if (i > 0) break;//xxxxxxxx
- const path& p = paths[i];
-
- if (p.m_fill0 == 0 && p.m_fill1 == 0) {
- continue;
- }
-
- gnash::render::set_matrix(mat);
-
- // Color the line according to which side has
- // fills.
- if (p.m_fill0 == 0) glColor4f(1, 0, 0, 0.5);
- else if (p.m_fill1 == 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.m_ax, p.m_ay));
- glVertex2f(pt.m_x, pt.m_y);
-
- for (unsigned int j = 0; j < p.m_edges.size(); j++) {
- mat.transform(&pt, point(p.m_edges[j].m_cx, p.m_edges[j].m_cy));
- glVertex2f(pt.m_x, pt.m_y);
- mat.transform(&pt, point(p.m_edges[j].m_ax, p.m_edges[j].m_ay));
- glVertex2f(pt.m_x, pt.m_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].m_cx, p.m_edges[j].m_cy));
- mat.transform(&p1, point(p.m_edges[j].m_ax, p.m_edges[j].m_ay));
- dir = point(p1.m_x - p0.m_x, p1.m_y - p0.m_y);
- point_normalize(&dir);
- right = point(-dir.m_y, dir.m_x); // perpendicular
-
- const float ARROW_MAG = 60.f; // TWIPS?
- if (p.m_fill0 != 0)
- {
- glColor4f(0, 1, 0, 0.5);
- glVertex2f(p0.m_x,
- p0.m_y);
- glVertex2f(p0.m_x - dir.m_x * ARROW_MAG - right.m_x *
ARROW_MAG,
- p0.m_y - dir.m_y * ARROW_MAG - right.m_y *
ARROW_MAG);
-
- show_fill_number(point(p0.m_x - right.m_x * ARROW_MAG *
4,
- p0.m_y - right.m_y * ARROW_MAG *
4),
- p.m_fill0);
- }
- if (p.m_fill1 != 0)
- {
- glColor4f(1, 0, 0, 0.5);
- glVertex2f(p0.m_x,
- p0.m_y);
- glVertex2f(p0.m_x - dir.m_x * ARROW_MAG + right.m_x *
ARROW_MAG,
- p0.m_y - dir.m_y * ARROW_MAG + right.m_y *
ARROW_MAG);
-
- show_fill_number(point(p0.m_x + right.m_x * ARROW_MAG *
4,
- p0.m_y + right.m_y * ARROW_MAG *
4),
- p.m_fill1);
- }
- }}
- glEnd();
-
- glPopMatrix();
- }
-}
-#endif // DEBUG_DISPLAY_SHAPE_PATHS
-
-
-void shape_character_def::display(
- const matrix& mat,
- const cxform& cx,
- float pixel_scale,
- const std::vector<fill_style>& fill_styles,
- const std::vector<line_style>& line_styles) const
- // Display our shape. Use the fill_styles arg to
- // override our default set of fill styles (e.g. when
- // rendering text).
-{
-// GNASH_REPORT_FUNCTION;
-
- // Compute the error tolerance in object-space.
- float max_scale = mat.get_max_scale();
- if (fabsf(max_scale) < 1e-6f) {
- // Scale is essentially zero.
- return;
- }
-
- float object_space_max_error = 20.0f / max_scale / pixel_scale *
s_curve_max_pixel_error;
-
-#ifdef DEBUG_DISPLAY_SHAPE_PATHS
- // Render a debug view of shape path outlines, instead
- // of the tesselated shapes themselves.
- if (gnash_debug_show_paths) {
- debug_display_shape_paths(mat, object_space_max_error, m_paths,
fill_styles, line_styles);
-
- return;
- }
-#endif // DEBUG_DISPLAY_SHAPE_PATHS
-
- // See if we have an acceptable mesh available; if so then render with it.
- for (unsigned int i = 0, n = m_cached_meshes.size(); i < n; i++) {
- const mesh_set* candidate = m_cached_meshes[i];
-
- if (object_space_max_error > candidate->get_error_tolerance() * 3.0f)
- {
- // Mesh is too high-res; the remaining meshes are higher res,
- // so stop searching and build an appropriately scaled mesh.
- break;
- }
-
- if (object_space_max_error > candidate->get_error_tolerance()) {
- // Do it.
- candidate->display(mat, cx, fill_styles, line_styles);
- return;
- }
- }
-
- // Construct a new mesh to handle this error tolerance.
- mesh_set* m = new mesh_set(this, object_space_max_error * 0.75f);
- m_cached_meshes.push_back(m);
- m->display(mat, cx, fill_styles, line_styles);
-
- sort_and_clean_meshes();
-}
-
-
-static int sort_by_decreasing_error(const void* A, const void* B)
-{
- const mesh_set* a = *(const mesh_set* const *) A;
- const mesh_set* b = *(const mesh_set* const *) B;
-
- if (a->get_error_tolerance() < b->get_error_tolerance()) {
- return 1;
- } else if (a->get_error_tolerance() > b->get_error_tolerance()) {
- return -1;
- } else {
- return 0;
- }
-}
-
-
-void shape_character_def::sort_and_clean_meshes() const
- // Maintain cached meshes. Clean out mesh_sets that haven't
- // been used recently, and make sure they're sorted from high
- // error to low error.
-{
- // Re-sort.
- if (m_cached_meshes.size() > 0) {
- qsort(
- &m_cached_meshes[0],
- m_cached_meshes.size(),
- sizeof(m_cached_meshes[0]),
- sort_by_decreasing_error);
-
- // Check to make sure the sort worked as intended.
-#ifndef NDEBUG
- for (unsigned int i = 0, n = m_cached_meshes.size() - 1; i < n; i++) {
- const mesh_set* a = m_cached_meshes[i];
- const mesh_set* b = m_cached_meshes[i + 1];
-
- assert(a->get_error_tolerance() > b->get_error_tolerance());
- }
-#endif // not NDEBUG
- }
-}
-
-
-void shape_character_def::tesselate(float error_tolerance,
tesselate::trapezoid_accepter* accepter) const
- // Push our shape data through the tesselator.
-{
- tesselate::begin_shape(accepter, error_tolerance);
- for (unsigned int i = 0; i < m_paths.size(); i++) {
- if (m_paths[i].m_new_shape == true) {
- // Hm; should handle separate sub-shapes in a less lame way.
- tesselate::end_shape();
- tesselate::begin_shape(accepter, error_tolerance);
- } else {
- m_paths[i].tesselate();
- }
- }
- tesselate::end_shape();
-}
-
-
-bool shape_character_def::point_test_local(float x, float y)
- // Return true if the specified point is on the interior of our shape.
- // Incoming coords are local coords.
-{
- if (m_bound.point_test(x, y) == false) {
- // Early out.
- return false;
- }
-
- // Try each of the paths.
- for (unsigned int i = 0; i < m_paths.size(); i++) {
- if (m_paths[i].point_test(x, y))
- {
- return true;
- }
- }
-
- return false;
-}
-
-
-float shape_character_def::get_height_local()
-{
- return m_bound.height();
-}
-
-float shape_character_def::get_width_local()
-{
- return m_bound.width();
-}
-
-
-void shape_character_def::compute_bound(rect* r) const
- // Find the bounds of this shape, and store them in
- // the given rectangle.
-{
- r->m_x_min = 1e10f;
- r->m_y_min = 1e10f;
- r->m_x_max = -1e10f;
- r->m_y_max = -1e10f;
-
- for (unsigned int i = 0; i < m_paths.size(); i++) {
- const path& p = m_paths[i];
- r->expand_to_point(p.m_ax, p.m_ay);
- for (unsigned int j = 0; j < p.m_edges.size(); j++) {
- r->expand_to_point(p.m_edges[j].m_ax, p.m_edges[j].m_ay);
-// r->expand_to_point(p.m_edges[j].m_cx,
p.m_edges[j].m_cy);
- }
- }
-}
-
-
-void shape_character_def::output_cached_data(tu_file* out, const
cache_options& /* options */)
- // Dump our precomputed mesh data to the given stream.
-{
- int n = m_cached_meshes.size();
- out->write_le32(n);
-
- for (int i = 0; i < n; i++) {
- m_cached_meshes[i]->output_cached_data(out);
- }
-}
-
-
-void shape_character_def::input_cached_data(tu_file* in)
- // Initialize our mesh data from the given stream.
-{
- int n = in->read_le32();
-
- m_cached_meshes.resize(n);
-
- for (int i = 0; i < n; i++) {
- mesh_set* ms = new mesh_set();
- ms->input_cached_data(in);
- m_cached_meshes[i] = ms;
- }
-}
-
-
-} // end namespace gnash
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
Index: server/shape_character_def.h
===================================================================
RCS file: server/shape_character_def.h
diff -N server/shape_character_def.h
--- server/shape_character_def.h 25 May 2006 12:05:16 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,85 +0,0 @@
-// shape.h -- Thatcher Ulrich <address@hidden> 2003
-
-// This source code has been donated to the Public Domain. Do
-// whatever you want with it.
-
-// Quadratic bezier outline shapes, the basis for most SWF rendering.
-
-
-#ifndef GNASH_SHAPE_CHARACTER_DEF_H
-#define GNASH_SHAPE_CHARACTER_DEF_H
-
-
-#include "styles.h"
-#include "character_def.h" // for inheritance of shape_character_def
-#include "tesselate.h"
-#include "shape.h" // for path
-
-
-namespace gnash {
-
- /// \brief
- /// Represents the outline of one or more shapes, along with
- /// information on fill and line styles.
- class shape_character_def : public character_def, public
tesselate::tesselating_shape
- {
- public:
- shape_character_def();
- virtual ~shape_character_def();
-
- virtual void display(character* inst);
- bool point_test_local(float x, float y);
-
- float get_height_local();
- float get_width_local();
-
- void read(stream* in, int tag_type, bool with_style,
movie_definition* m);
- void display(
- const matrix& mat,
- const cxform& cx,
- float pixel_scale,
- const std::vector<fill_style>& fill_styles,
- const std::vector<line_style>& line_styles) const;
- virtual void tesselate(float error_tolerance,
tesselate::trapezoid_accepter* accepter) const;
- const rect& get_bound() const { return m_bound; }
- void compute_bound(rect* r) const; // @@ what's the
difference between this and get_bound?
-
- void output_cached_data(tu_file* out, const cache_options&
options);
- void input_cached_data(tu_file* in);
-
- const std::vector<fill_style>& get_fill_styles() const {
return m_fill_styles; }
- const std::vector<line_style>& get_line_styles() const {
return m_line_styles; }
- 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 */ }
-
- protected:
- friend class morph2_character_def;
-
- // derived morph classes changes these
- std::vector<fill_style> m_fill_styles;
- std::vector<line_style> m_line_styles;
- std::vector<path> m_paths;
-
- private:
- void sort_and_clean_meshes() const;
-
- rect m_bound;
-
- // Cached pre-tesselated meshes.
- mutable std::vector<mesh_set*> m_cached_meshes;
- };
-
-} // end namespace gnash
-
-
-#endif // GNASH_SHAPE_CHARACTER_DEF_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
Index: server/sprite_definition.cpp
===================================================================
RCS file: server/sprite_definition.cpp
diff -N server/sprite_definition.cpp
--- server/sprite_definition.cpp 13 Aug 2006 16:45:11 -0000 1.13
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,181 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-// This needs to be included first for NetBSD systems or we get a weird
-// problem with pthread_t being defined too many times if we use any
-// STL containers.
-#ifdef HAVE_PTHREADS
-#include <pthread.h>
-#endif
-
-#include "sprite_instance.h"
-#include "sprite_definition.h"
-#include "execute_tag.h" // for dtor visibility
-
-#include <vector>
-#include <string>
-#include <cassert>
-
-using namespace std;
-
-namespace gnash {
-
-character*
-sprite_definition::create_character_instance(character* parent,
- int id)
-{
- sprite_instance* si = new sprite_instance(this,
- parent->get_root(), parent, id);
- return si;
-}
-
-sprite_definition::~sprite_definition()
-{
- // Release our playlist data.
- for (int i = 0, n = m_playlist.size(); i < n; i++)
- {
- for (int j = 0, m = m_playlist[i].size(); j < m; j++)
- {
- delete m_playlist[i][j];
- }
- }
-}
-
-/*private*/
-// only called from constructors
-void
-sprite_definition::read(stream* in)
-{
- int tag_end = in->get_tag_end_position();
-
- m_frame_count = in->read_u16();
-
- // ALEX: some SWF files have been seen that have 0-frame sprites.
- // The Macromedia player behaves as if they have 1 frame.
- if (m_frame_count < 1)
- {
- m_frame_count = 1;
- }
-
- // need a playlist for each frame
- m_playlist.resize(m_frame_count);
-
- IF_VERBOSE_PARSE (
- log_parse(" frames = %u", m_frame_count);
- );
-
- m_loading_frame = 0;
-
- while ((uint32_t) in->get_position() < (uint32_t) tag_end)
- {
- SWF::tag_type tag_type = in->open_tag();
-
- SWF::TagLoadersTable::loader_function lf = NULL;
-
- if (tag_type == SWF::DEFINESPRITE)
- {
- log_error("DefineSprite tag inside sprite "
- "definition - Malformed SWF!");
- }
-
- if (tag_type == SWF::SHOWFRAME)
- {
- // show frame tag -- advance to the next frame.
- IF_VERBOSE_PARSE (
- log_parse(" show_frame (sprite)");
- );
- m_loading_frame++;
- }
- else if (_tag_loaders.get(tag_type, &lf))
- {
- // call the tag loader. The tag loader should add
- // characters or tags to the movie data structure.
- (*lf)(in, tag_type, this);
- }
- else
- {
- // no tag loader for this tag type.
- log_error("*** no tag loader for type %d (sprite)",
- tag_type);
- }
-
- in->close_tag();
- }
-
- IF_VERBOSE_PARSE (
- log_parse(" -- sprite END --");
- );
-}
-
-/*virtual*/
-void
-sprite_definition::add_frame_name(const char* name)
-{
- assert((int)m_loading_frame >= 0 && m_loading_frame < m_frame_count);
-
- tu_string n = name;
- size_t currently_assigned = 0;
- if (m_named_frames.get(n, ¤tly_assigned) == true)
- {
- log_error("add_frame_name(%d, '%s') -- frame name "
- "already assigned to frame %u; overriding\n",
- m_loading_frame,
- name, currently_assigned);
- }
-
- // stores 0-based frame #
- m_named_frames[n] = m_loading_frame;
-}
-
-sprite_definition::sprite_definition(movie_definition* m, stream* in)
- :
- _tag_loaders(s_tag_loaders), // FIXME: use a class-static
TagLoadersTable for sprite_definition
- m_movie_def(m),
- m_frame_count(0),
- m_loading_frame(0)
-{
- assert(m_movie_def);
- read(in);
-}
-
-
-
-} // namespace gnash
Index: server/sprite_definition.h
===================================================================
RCS file: server/sprite_definition.h
diff -N server/sprite_definition.h
--- server/sprite_definition.h 14 Aug 2006 23:16:57 -0000 1.16
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,369 +0,0 @@
-//
-// Copyright (C) 2005, 2006 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 2 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
-
-// Linking Gnash statically or dynamically with other modules is making a
-// combined work based on Gnash. Thus, the terms and conditions of the GNU
-// General Public License cover the whole combination.
-//
-// As a special exception, the copyright holders of Gnash give you
-// permission to combine Gnash with free software programs or libraries
-// that are released under the GNU LGPL and with code included in any
-// release of Talkback distributed by the Mozilla Foundation. You may
-// copy and distribute such a system following the terms of the GNU GPL
-// for all but the LGPL-covered parts and Talkback, and following the
-// LGPL for the LGPL-covered parts.
-//
-// Note that people who make modified versions of Gnash are not obligated
-// to grant this special exception for their modified versions; it is their
-// choice whether to do so. The GNU General Public License gives permission
-// to release a modified version without this exception; this exception
-// also makes it possible to release a modified version which carries
-// forward this exception.
-//
-//
-
-#ifndef GNASH_SPRITE_DEFINITION_H
-#define GNASH_SPRITE_DEFINITION_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <vector>
-
-#include "movie_definition.h"
-#include "stream.h"
-#include "log.h"
-
-namespace gnash
-{
-
-
-/// \brief
-/// Holds the immutable data for a sprite, as read from
-/// as SWF stream.
-/// @@ should *not* derive from movie_definition, probably!
-///
-class sprite_definition : public movie_definition
-{
-
-public:
-
- /// \brief
- /// Read the sprite info from input stream.
- //
- /// A sprite definition consists of a series control tags.
- ///
- /// @param m
- /// the Top-Level movie_definition this sprite is read
- /// from (not a sprite_definition!)
- ///
- /// @param in
- /// The stream associated with the sprite. It is assumed
- /// to be already positioned right before the frame count
- ///
- sprite_definition(movie_definition* m, stream* in);
-
- /// Destructor, releases playlist data
- ~sprite_definition();
-
-private:
-
- void read(stream* in);
-
- /// Tags loader table.
- //
- /// TODO: make it a static member, specific to sprite_definition
- SWF::TagLoadersTable& _tag_loaders;
-
- /// Top-level movie definition
- /// (the definition read from SWF stream)
- movie_definition* m_movie_def;
-
- /// movie control events for each frame.
- std::vector<std::vector<execute_tag*> > m_playlist;
-
- // stores 0-based frame #'s
- stringi_hash<size_t> m_named_frames;
-
- size_t m_frame_count;
-
- size_t m_loading_frame;
-
- // overloads from movie_definition
- virtual float get_width_pixels() const { return 1; }
- virtual float get_height_pixels() const { return 1; }
-
- virtual size_t get_frame_count() const
- {
- return m_frame_count;
- }
-
- /// \brief
- /// Return total bytes of the movie from which this sprite
- /// has been read.
- ///
- virtual size_t get_bytes_total() const
- {
- return m_movie_def->get_bytes_total();
- }
-
- /// \brief
- /// Return the number of bytes loaded from the stream of the
- /// the movie from which this sprite is being read.
- ///
- virtual size_t get_bytes_loaded() const
- {
- return m_movie_def->get_bytes_loaded();
- }
-
- virtual float get_frame_rate() const { return
m_movie_def->get_frame_rate(); }
-
- // Return number of frames loaded (of current sprite)
- virtual size_t get_loading_frame() const { return m_loading_frame; }
-
- virtual int get_version() const { return
m_movie_def->get_version(); }
-
- virtual void add_font(int /*id*/, font* /*ch*/)
- {
- log_error("add_font tag appears in sprite tags! "
- "Malformed SWF?\n");
- }
-
- virtual font* get_font(int id) { return m_movie_def->get_font(id); }
-
- virtual void set_jpeg_loader(std::auto_ptr<jpeg::input> /*j_in*/)
- {
- assert(0);
- }
-
- virtual jpeg::input* get_jpeg_loader()
- {
- return NULL;
- }
-
- virtual bitmap_character_def* get_bitmap_character(int id)
- {
- return m_movie_def->get_bitmap_character(id);
- }
-
- virtual void add_bitmap_character(int /*id*/,
- bitmap_character_def* /*ch*/)
- {
- log_error("add_bc appears in sprite tags!"
- " Malformed SWF?");
- }
-
- virtual sound_sample* get_sound_sample(int id)
- {
- return m_movie_def->get_sound_sample(id);
- }
-
- virtual void add_sound_sample(int /*id*/, sound_sample* /*sam*/)
- {
- log_error("add sam appears in sprite tags!"
- " Malformed SWF?");
- }
-
- virtual void set_loading_sound_stream_id(int id) {
- return m_movie_def->set_loading_sound_stream_id(id);
- }
-
- virtual int get_loading_sound_stream_id() {
- return m_movie_def->get_loading_sound_stream_id();
- }
-
-
- // @@ would be nicer to not inherit these...
- virtual create_bitmaps_flag get_create_bitmaps() const
- { assert(0); return DO_LOAD_BITMAPS; }
- virtual create_font_shapes_flag get_create_font_shapes() const
- { assert(0); return DO_LOAD_FONT_SHAPES; }
- virtual int get_bitmap_info_count() const
- { assert(0); return 0; }
- virtual bitmap_info* get_bitmap_info(int /*i*/) const
- { assert(0); return NULL; }
- virtual void add_bitmap_info(bitmap_info* /*bi*/)
- { assert(0); }
-
- virtual void export_resource(const tu_string& /*symbol*/,
- resource* /*res*/)
- {
- log_error("can't export from sprite! Malformed SWF?");
- }
-
- virtual smart_ptr<resource> get_exported_resource(const tu_string& sym)
- {
- return m_movie_def->get_exported_resource(sym);
- }
-
- virtual void add_import(const char* /*source_url*/, int /*id*/,
- const char* /*symbol*/)
- {
- assert(0);
- }
-
- virtual void visit_imported_movies(import_visitor* /*v*/)
- {
- assert(0);
- }
-
- virtual void resolve_import(const char* /*source_url*/,
- movie_definition* /*d*/)
- {
- assert(0);
- }
-
-
- /// \brief
- /// Get a character_def from this Sprite's parent
- /// CharacterDictionary. NOTE that calling this
- /// method on the leaf Sprite of a movie_definition
- /// hierarchy will result in a recursive scan of
- /// all parents until the top-level movie_definition
- /// (movie_def_impl) is found.
- ///
- virtual character_def* get_character_def(int id)
- {
- return m_movie_def->get_character_def(id);
- }
-
- /// Calls to this function should only be made when
- /// an invalid SWF is being read, as it would mean
- /// that a Definition tag is been found as part of
- /// a Sprite definition
- ///
- virtual void add_character(int /*id*/, character_def* /*ch*/)
- {
- log_error("add_character tag appears in sprite tags!"
- " Maformed SWF?");
- }
-
-
- virtual void generate_font_bitmaps()
- {
- assert(0);
- }
-
- virtual void output_cached_data(tu_file* /*out*/,
- const cache_options& /*options*/)
- {
- // Nothing to do.
- return;
- }
-
- virtual void input_cached_data(tu_file* /*in*/)
- {
- // Nothing to do.
- return;
- }
-
- virtual movie_interface* create_instance()
- {
- return NULL;
- }
-
- // Create a (mutable) instance of our definition. The
- // instance is created to live (temporarily) on some level on
- // the parent movie's display list.
- //
- // overloads from character_def
- virtual character* create_character_instance(
- character* parent, int id);
-
-
- virtual void add_execute_tag(execute_tag* c)
- {
- m_playlist[m_loading_frame].push_back(c);
- }
-
- //virtual void add_init_action(int sprite_id, execute_tag* c)
- virtual void add_init_action(execute_tag* /*c*/)
- {
- // Sprite def's should not have do_init_action tags in them! (@@
correct?)
- log_error("sprite_definition::add_init_action called! Ignored.
(Malformed SWF?)\n");
- }
-
- /// \brief
- /// Labels the frame currently being loaded with the
- /// given name. A copy of the name string is made and
- /// kept in this object.
- ///
- virtual void add_frame_name(const char* name);
-
- /// Returns 0-based frame #
- bool get_labeled_frame(const char* label, size_t* frame_number)
- {
- return m_named_frames.get(label, frame_number);
- }
-
- /// frame_number is 0-based
- const std::vector<execute_tag*>& get_playlist(size_t frame_number)
- {
- return m_playlist[frame_number];
- }
-
- // Sprites do not have init actions in their
- // playlists! Only the root movie
- // (movie_def_impl) does (@@ correct?)
- virtual const std::vector<execute_tag*>* get_init_actions(size_t
/*frame_number*/)
- {
- return NULL;
- }
-
- virtual const std::string& get_url() const
- {
- return m_movie_def->get_url();
- }
-
- /// \brief
- /// Ensure framenum frames of this sprite
- /// have been loaded.
- ///
- virtual bool ensure_frame_loaded(size_t framenum)
- {
- // TODO: return false on timeout
- while ( m_loading_frame < framenum )
- {
- log_msg("sprite_definition: "
- "loading of frame %u requested "
- "(we are at %u/%u)",
- framenum, m_loading_frame, m_frame_count);
- // Could this ever happen ?
- assert(0);
- }
- return true;
- }
-
- virtual void load_next_frame_chunk()
- {
- /// We load full sprite definitions at once, so
- /// this function is a no-op.
- }
-
- /// Return the top-level movie definition
- /// (the definition read from SWF stream)
- movie_definition* get_movie_definition() {
- return m_movie_def;
- }
-
-
-};
-
-
-} // end of namespace gnash
-
-#endif // GNASH_SPRITE_H
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ChangeLog configure.ac gui/Makefile.am gu...,
Sandro Santilli <=