gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r10779: Major reorganization of the


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10779: Major reorganization of the messy half of Gnash to match the neater half
Date: Tue, 07 Apr 2009 18:32:11 +0200
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10779
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Tue 2009-04-07 18:32:11 +0200
message:
  Major reorganization of the messy half of Gnash to match the neater half
  and implement the suppposed design consistently. Add a proper DisplayObject
  for MorphShape. The main changes are:
  
  - Rename character_def to DefinitionTag.
  - Rename shape_character_def to DefineShapeTag.
  - Move almost all parsing under the swf directory.
  - Make DefinitionTags really immutable and non-copyable.
  - Only faked definition tag now in MovieClip (though BitmapMovieDefinition
    also comes close).
  - Use the presence of a DefinitionTag to distinguish SWF-defined from
    dynamic DisplayObjects (except in MovieClip).
  - Make DynamicShape and ShapeRecord normal, non-refcounted or GC classes
    for stack allocation and smart-pointer usage.
  - Much more const correctness.
  - More logical design with proper class documentation.
  - Smaller and more consistent renderer interface for shape drawing.
  - GC resources reduced for all glyphs, morph definitions, dynamic shapes,
    BitmapMovies.
removed:
  libcore/Sprite.h
  libcore/parser/character_def.cpp
added:
  libcore/Geometry.cpp
  libcore/MorphShape.cpp
  libcore/MorphShape.h
  libcore/swf/ShapeRecord.cpp
  libcore/swf/ShapeRecord.h
renamed:
  libcore/parser/character_def.h => libcore/swf/DefinitionTag.h
  libcore/parser/morph2_character_def.cpp => libcore/swf/DefineMorphShapeTag.cpp
  libcore/parser/morph2_character_def.h => libcore/swf/DefineMorphShapeTag.h
  libcore/parser/shape_character_def.cpp => libcore/swf/DefineShapeTag.cpp
  libcore/parser/shape_character_def.h => libcore/swf/DefineShapeTag.h
modified:
  backend/Makefile.am
  backend/PathParser.cpp
  backend/PathParser.h
  backend/render_handler.h
  backend/render_handler_agg.cpp
  backend/render_handler_cairo.cpp
  backend/render_handler_ogl.cpp
  backend/render_handler_ogl.h
  cygnal/Makefile.am
  gui/Makefile.am
  libcore/Bitmap.cpp
  libcore/Bitmap.h
  libcore/BitmapMovieInstance.cpp
  libcore/Button.cpp
  libcore/DisplayObject.h
  libcore/DynamicShape.cpp
  libcore/DynamicShape.h
  libcore/ExportableResource.h
  libcore/Font.cpp
  libcore/Font.h
  libcore/FreetypeGlyphsProvider.cpp
  libcore/FreetypeGlyphsProvider.h
  libcore/Geometry.h
  libcore/InteractiveObject.h
  libcore/Makefile.am
  libcore/MouseButtonState.h
  libcore/MovieClip.cpp
  libcore/MovieClip.h
  libcore/Shape.cpp
  libcore/Shape.h
  libcore/StaticText.cpp
  libcore/StaticText.h
  libcore/TextField.cpp
  libcore/Video.cpp
  libcore/as_environment.cpp
  libcore/fill_style.h
  libcore/fontlib.cpp
  libcore/impl.cpp
  libcore/movie_root.cpp
  libcore/parser/BitmapMovieDefinition.cpp
  libcore/parser/BitmapMovieDefinition.h
  libcore/parser/Makefile.am
  libcore/parser/SWFMovieDefinition.cpp
  libcore/parser/SWFMovieDefinition.h
  libcore/parser/movie_definition.h
  libcore/parser/sprite_definition.cpp
  libcore/parser/sprite_definition.h
  libcore/render.cpp
  libcore/render.h
  libcore/swf/DefineButtonCxformTag.cpp
  libcore/swf/DefineButtonSoundTag.cpp
  libcore/swf/DefineButtonTag.cpp
  libcore/swf/DefineButtonTag.h
  libcore/swf/DefineEditTextTag.h
  libcore/swf/DefineFontTag.cpp
  libcore/swf/DefineTextTag.cpp
  libcore/swf/DefineTextTag.h
  libcore/swf/DefineVideoStreamTag.h
  libcore/swf/TextRecord.cpp
  libcore/swf/TextRecord.h
  libcore/swf/VideoFrameTag.cpp
  libcore/swf/VideoFrameTag.h
  libcore/swf/tag_loaders.cpp
  libcore/swf/tag_loaders.h
  testsuite/Makefile.am
  testsuite/libcore.all/ClassSizes.cpp
  testsuite/libcore.all/EdgeTest.cpp
  testsuite/libcore.all/Makefile.am
  testsuite/misc-ming.all/Makefile.am
  testsuite/misc-swfc.all/Makefile.am
  testsuite/misc-swfmill.all/Makefile.am
  testsuite/movies.all/Makefile.am
  testsuite/samples/Makefile.am
  utilities/Makefile.am
  libcore/swf/DefinitionTag.h
  libcore/swf/DefineMorphShapeTag.cpp
  libcore/swf/DefineMorphShapeTag.h
  libcore/swf/DefineShapeTag.cpp
  libcore/swf/DefineShapeTag.h
    ------------------------------------------------------------
    revno: 10771.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sun 2009-04-05 13:11:30 +0200
    message:
      Alter header guards.
    modified:
      libcore/DisplayObject.h
      libcore/StaticText.h
    ------------------------------------------------------------
    revno: 10771.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sun 2009-04-05 13:28:44 +0200
    message:
      Minor cleanup.
    modified:
      libcore/parser/movie_definition.h
    ------------------------------------------------------------
    revno: 10771.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sun 2009-04-05 13:45:17 +0200
    message:
      Drop Sprite.h, as its information was either wrong or not very useful.
    removed:
      libcore/Sprite.h
    modified:
      libcore/Makefile.am
    ------------------------------------------------------------
    revno: 10771.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 10:16:33 +0200
    message:
      Add MorphShape class. This is mainly for AVM2, but also helps separate
      parsing and execution for AVM1 by storing mutable state information in
      a DisplayObject, not a character definition.
    added:
      libcore/MorphShape.cpp
      libcore/MorphShape.h
    modified:
      backend/render_handler.h
      backend/render_handler_agg.cpp
      libcore/Makefile.am
      libcore/MovieClip.cpp
      libcore/fill_style.h
      libcore/movie_root.cpp
      libcore/parser/character_def.h
      libcore/parser/morph2_character_def.cpp
      libcore/parser/morph2_character_def.h
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
      libcore/swf/tag_loaders.cpp
    ------------------------------------------------------------
    revno: 10771.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 10:56:17 +0200
    message:
      Restrict renderer interface to drawShape and drawMorph, each taking a 
      definition and a DisplayObject. This is much neater and more consistent.
    modified:
      backend/render_handler.h
      backend/render_handler_agg.cpp
      libcore/Bitmap.cpp
      libcore/Shape.cpp
      libcore/parser/morph2_character_def.cpp
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
      libcore/render.cpp
      libcore/render.h
    ------------------------------------------------------------
    revno: 10771.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 12:18:59 +0200
    message:
      Move non-class-specific hit and crossing tests to Geometry.h. Drop
      duplicated functions. Remove class typedef and use the actual name
      everywhere. Indentation.
    modified:
      backend/render_handler_agg.cpp
      libcore/Bitmap.cpp
      libcore/DynamicShape.cpp
      libcore/DynamicShape.h
      libcore/Geometry.h
      libcore/Makefile.am
      libcore/MorphShape.cpp
      libcore/MorphShape.h
      libcore/Shape.cpp
      libcore/parser/BitmapMovieDefinition.cpp
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
    ------------------------------------------------------------
    revno: 10771.1.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 12:24:21 +0200
    message:
      Add Geometry.cpp.
    added:
      libcore/Geometry.cpp
    ------------------------------------------------------------
    revno: 10771.1.8
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 13:16:20 +0200
    message:
      Register MorphShape as a live char so that advance is called.
    modified:
      libcore/MorphShape.cpp
      libcore/MorphShape.h
      libcore/MovieClip.cpp
      libcore/Video.cpp
      libcore/parser/sprite_definition.cpp
    ------------------------------------------------------------
    revno: 10771.1.9
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 13:31:51 +0200
    message:
      Fix EdgeTest by using correct class name.
    modified:
      testsuite/libcore.all/EdgeTest.cpp
    ------------------------------------------------------------
    revno: 10771.1.10
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 15:27:04 +0200
    message:
      Re-add pointTestLocal to shape_character_def, as DynamicShape has to 
override
      it. Remove from base class character_def as it only make sense for 
shape-like
      characters. It also reveals StaticText had been using the default
      implementation. MorphShape uses geometry::pointTest directly.
      
      Initialize MorphShape members to match shape1 on construction instead of
      the messy way it was done before.
    modified:
      libcore/DynamicShape.h
      libcore/Geometry.cpp
      libcore/Geometry.h
      libcore/MorphShape.cpp
      libcore/Shape.cpp
      libcore/StaticText.cpp
      libcore/parser/character_def.h
      libcore/parser/morph2_character_def.cpp
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
    ------------------------------------------------------------
    revno: 10771.1.11
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 17:32:26 +0200
    message:
      There are two ways of morphing: either a PlaceObject tag with a move flag,
      or remove and re-add the morph shape with a different ratio. Call morph()
      in the stagePlacementCallback if ratio is not 0 to handle the second
      (less efficient) case.
    modified:
      libcore/MorphShape.cpp
      libcore/MorphShape.h
    ------------------------------------------------------------
    revno: 10771.1.12
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 18:21:49 +0200
    message:
      Merge from trunk.
      
      Drop advance() code, as it messes up the morph timing in relation to
      MovieClip's advance. MorphShape isn't a LiveChar anymore; morphing is
      done on display() again.
    modified:
      libcore/MorphShape.cpp
      libcore/MorphShape.h
      pythonmodule/gnashPythonExample.py
      pythonmodule/gnashpython.cpp
      pythonmodule/gnashpython.h
      pythonmodule/pyGnash.cpp
    ------------------------------------------------------------
    revno: 10771.1.13
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 19:08:48 +0200
    message:
      Indentation, minor correction.
    modified:
      libcore/parser/shape_character_def.cpp
    ------------------------------------------------------------
    revno: 10771.1.14
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 20:29:44 +0200
    message:
      Construct morph definition directly from SWFStream.
    modified:
      libcore/parser/morph2_character_def.cpp
      libcore/parser/morph2_character_def.h
      libcore/swf/tag_loaders.cpp
    ------------------------------------------------------------
    revno: 10771.1.15
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 21:22:40 +0200
    message:
      Add ShapeRecord, a neutral container for shape information.
    added:
      libcore/swf/ShapeRecord.cpp
      libcore/swf/ShapeRecord.h
    modified:
      libcore/Makefile.am
    ------------------------------------------------------------
    revno: 10771.1.16
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-04-06 22:29:42 +0200
    message:
      Use ShapeRecord in morph shapes.
    modified:
      backend/Makefile.am
      cygnal/Makefile.am
      gui/Makefile.am
      libcore/MorphShape.cpp
      libcore/parser/morph2_character_def.cpp
      libcore/parser/morph2_character_def.h
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
      libcore/swf/ShapeRecord.cpp
      libcore/swf/ShapeRecord.h
      utilities/Makefile.am
    ------------------------------------------------------------
    revno: 10771.1.17
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 07:03:54 +0200
    message:
      Const correctness. The morph class no longer needs shape_character_def.
      Fix invalidated bounds of morph for display. Needs testing for AS bounds
      in AVM2.
    modified:
      libcore/MorphShape.cpp
      libcore/MorphShape.h
      libcore/parser/morph2_character_def.cpp
      libcore/parser/morph2_character_def.h
      libcore/parser/shape_character_def.h
    ------------------------------------------------------------
    revno: 10771.1.18
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 08:52:54 +0200
    message:
      Move morph parsing under swf directory.
    renamed:
      libcore/parser/morph2_character_def.cpp => 
libcore/swf/DefineMorphShapeTag.cpp
      libcore/parser/morph2_character_def.h => libcore/swf/DefineMorphShapeTag.h
    modified:
      backend/render_handler.h
      backend/render_handler_agg.cpp
      libcore/Makefile.am
      libcore/MorphShape.cpp
      libcore/MorphShape.h
      libcore/impl.cpp
      libcore/parser/Makefile.am
      libcore/parser/character_def.h
      libcore/render.cpp
      libcore/render.h
      libcore/swf/ShapeRecord.h
      libcore/swf/tag_loaders.cpp
      libcore/swf/tag_loaders.h
      libcore/swf/DefineMorphShapeTag.cpp
      libcore/swf/DefineMorphShapeTag.h
    ------------------------------------------------------------
    revno: 10771.1.19
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 09:18:30 +0200
    message:
      Start separating DynamicShape and shape_character_def. No display after 
this commit.
    modified:
      libcore/DynamicShape.cpp
      libcore/DynamicShape.h
      libcore/swf/ShapeRecord.h
    ------------------------------------------------------------
    revno: 10771.1.20
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 11:19:54 +0200
    message:
      Separate DynamicShape completely from shape_character_def.
      
      DynamicShape is not refcounted, so management is always up to the users
      (not yet implemented properly).
      
      DynamicShape is used for Fonts (glyphs), Bitmaps, BitmapMovies and the
      movie_root drawable.
      
      All character_defs should now be immutable and noncopyable.
    modified:
      backend/render_handler.h
      backend/render_handler_agg.cpp
      libcore/Bitmap.cpp
      libcore/Bitmap.h
      libcore/BitmapMovieInstance.cpp
      libcore/DynamicShape.cpp
      libcore/DynamicShape.h
      libcore/Font.cpp
      libcore/Font.h
      libcore/FreetypeGlyphsProvider.cpp
      libcore/FreetypeGlyphsProvider.h
      libcore/Geometry.cpp
      libcore/MovieClip.cpp
      libcore/MovieClip.h
      libcore/Shape.cpp
      libcore/Shape.h
      libcore/parser/BitmapMovieDefinition.cpp
      libcore/parser/BitmapMovieDefinition.h
      libcore/parser/character_def.h
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
      libcore/render.cpp
      libcore/render.h
      libcore/swf/DefineFontTag.cpp
      libcore/swf/TextRecord.cpp
      libcore/swf/tag_loaders.cpp
      testsuite/Makefile.am
      testsuite/misc-ming.all/Makefile.am
    ------------------------------------------------------------
    revno: 10771.1.21
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 11:49:53 +0200
    message:
      Drop most of shape_character_def interface now it's not used.
    modified:
      libcore/Shape.cpp
      libcore/as_environment.cpp
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
      libcore/swf/DefineMorphShapeTag.cpp
      libcore/swf/ShapeRecord.cpp
      testsuite/movies.all/Makefile.am
      testsuite/samples/Makefile.am
    ------------------------------------------------------------
    revno: 10771.1.22
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 13:14:10 +0200
    message:
      Add documentation for various classes. Const correct definitions and
      member functions. Add libcore/swf to testsuite Makefiles so the testsuite
      builds and runs again. One failure.
    modified:
      libcore/DisplayObject.h
      libcore/DynamicShape.cpp
      libcore/DynamicShape.h
      libcore/Font.cpp
      libcore/Font.h
      libcore/FreetypeGlyphsProvider.cpp
      libcore/FreetypeGlyphsProvider.h
      libcore/Shape.h
      libcore/StaticText.cpp
      libcore/StaticText.h
      libcore/TextField.cpp
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
      libcore/swf/DefineFontTag.cpp
      libcore/swf/DefineMorphShapeTag.cpp
      libcore/swf/DefineTextTag.cpp
      libcore/swf/DefineTextTag.h
      libcore/swf/ShapeRecord.h
      libcore/swf/TextRecord.cpp
      libcore/swf/TextRecord.h
      testsuite/misc-swfc.all/Makefile.am
      testsuite/misc-swfmill.all/Makefile.am
    ------------------------------------------------------------
    revno: 10771.1.23
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 14:23:59 +0200
    message:
      Use ShapeRecord, not DynamicShape for Freetype font walking. This trades
      a bit of code duplication (could be reduced) for a much cleaner interface
      and less memory per glyph.
    modified:
      libcore/DynamicShape.cpp
      libcore/FreetypeGlyphsProvider.cpp
    ------------------------------------------------------------
    revno: 10771.1.24
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 14:28:39 +0200
    message:
      Boilerplate and file descriptions.
    modified:
      libcore/Geometry.cpp
      libcore/Geometry.h
      libcore/MorphShape.cpp
      libcore/MorphShape.h
      libcore/Shape.cpp
      libcore/Shape.h
      libcore/StaticText.cpp
      libcore/StaticText.h
      libcore/swf/ShapeRecord.cpp
      libcore/swf/ShapeRecord.h
    ------------------------------------------------------------
    revno: 10771.1.25
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 14:34:43 +0200
    message:
      Move shape_character_def and character_def. Rename to DefineShapeTag
      and DefinitionTag.
    renamed:
      libcore/parser/character_def.cpp => libcore/swf/DefinitionTag.cpp
      libcore/parser/character_def.h => libcore/swf/DefinitionTag.h
      libcore/parser/shape_character_def.cpp => libcore/swf/DefineShapeTag.cpp
      libcore/parser/shape_character_def.h => libcore/swf/DefineShapeTag.h
    modified:
      backend/render_handler.h
      backend/render_handler_agg.cpp
      backend/render_handler_cairo.cpp
      backend/render_handler_ogl.cpp
      libcore/Bitmap.h
      libcore/Button.cpp
      libcore/DisplayObject.h
      libcore/DynamicShape.h
      libcore/ExportableResource.h
      libcore/Font.h
      libcore/FreetypeGlyphsProvider.h
      libcore/Geometry.h
      libcore/InteractiveObject.h
      libcore/Makefile.am
      libcore/MouseButtonState.h
      libcore/MovieClip.cpp
      libcore/MovieClip.h
      libcore/Shape.h
      libcore/StaticText.cpp
      libcore/StaticText.h
      libcore/fontlib.cpp
      libcore/parser/BitmapMovieDefinition.cpp
      libcore/parser/Makefile.am
      libcore/parser/SWFMovieDefinition.cpp
      libcore/parser/SWFMovieDefinition.h
      libcore/parser/movie_definition.h
      libcore/parser/sprite_definition.h
      libcore/render.cpp
      libcore/render.h
      libcore/swf/DefineButtonCxformTag.cpp
      libcore/swf/DefineButtonSoundTag.cpp
      libcore/swf/DefineButtonTag.cpp
      libcore/swf/DefineButtonTag.h
      libcore/swf/DefineEditTextTag.h
      libcore/swf/DefineMorphShapeTag.h
      libcore/swf/DefineTextTag.h
      libcore/swf/DefineVideoStreamTag.h
      libcore/swf/VideoFrameTag.cpp
      libcore/swf/VideoFrameTag.h
      libcore/swf/tag_loaders.cpp
      libcore/swf/DefinitionTag.cpp
      libcore/swf/DefinitionTag.h
      libcore/swf/DefineShapeTag.cpp
      libcore/swf/DefineShapeTag.h
    ------------------------------------------------------------
    revno: 10771.1.26
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 14:45:25 +0200
    message:
      Rename more.
    removed:
      libcore/swf/DefinitionTag.cpp
    modified:
      libcore/Makefile.am
      libcore/Shape.h
      libcore/impl.cpp
      libcore/parser/SWFMovieDefinition.h
      libcore/parser/movie_definition.h
      libcore/parser/sprite_definition.h
      libcore/swf/DefineShapeTag.cpp
      libcore/swf/DefineShapeTag.h
      libcore/swf/DefinitionTag.h
      libcore/swf/tag_loaders.cpp
      libcore/swf/tag_loaders.h
    ------------------------------------------------------------
    revno: 10771.1.27
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 14:46:29 +0200
    message:
      Rename some functions mangled by sed.
    modified:
      libcore/MovieClip.cpp
      libcore/TextField.cpp
      libcore/parser/SWFMovieDefinition.cpp
      libcore/parser/SWFMovieDefinition.h
      libcore/parser/movie_definition.h
      libcore/swf/DefineButtonCxformTag.cpp
      libcore/swf/DefineButtonSoundTag.cpp
      libcore/swf/DefineButtonTag.cpp
      libcore/swf/VideoFrameTag.cpp
      libcore/swf/tag_loaders.cpp
    ------------------------------------------------------------
    revno: 10771.1.28
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 14:51:13 +0200
    message:
      Fix a couple of function names.
    modified:
      libcore/parser/sprite_definition.h
    ------------------------------------------------------------
    revno: 10771.1.29
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 14:52:56 +0200
    message:
      Fix another couple of function names.
    modified:
      libcore/parser/SWFMovieDefinition.cpp
    ------------------------------------------------------------
    revno: 10771.1.30
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 14:56:44 +0200
    message:
      Drop old drawShape renderer function.
    modified:
      backend/render_handler.h
      backend/render_handler_agg.cpp
      libcore/MovieClip.cpp
      libcore/render.cpp
      libcore/render.h
    ------------------------------------------------------------
    revno: 10771.1.31
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 15:07:42 +0200
    message:
      Move under namespace SWF as expected.
    modified:
      libcore/swf/DefineShapeTag.cpp
    ------------------------------------------------------------
    revno: 10771.1.32
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 15:13:16 +0200
    message:
      Header cleanup.
    modified:
      libcore/DisplayObject.h
      libcore/InteractiveObject.h
      libcore/MouseButtonState.h
      libcore/parser/movie_definition.h
    ------------------------------------------------------------
    revno: 10771.1.33
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 15:26:18 +0200
    message:
      Restore renderer bounds check and silence DynamicShape::display logging.
    modified:
      backend/render_handler_agg.cpp
      libcore/DynamicShape.cpp
    ------------------------------------------------------------
    revno: 10771.1.34
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 15:42:26 +0200
    message:
      Enable the bounds test again so that the whole testsuite passes.
    modified:
      libcore/Geometry.cpp
      libcore/Shape.cpp
    ------------------------------------------------------------
    revno: 10771.1.35
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 15:44:07 +0200
    message:
      Silence debugging.
    modified:
      libcore/Geometry.cpp
    ------------------------------------------------------------
    revno: 10771.1.36
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 16:00:27 +0200
    message:
      Fix cairo build.
    modified:
      backend/PathParser.cpp
      backend/PathParser.h
      backend/render_handler_cairo.cpp
    ------------------------------------------------------------
    revno: 10771.1.37
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 16:32:06 +0200
    message:
      Make sure all MorphShape's invalidated bounds are returned in getBounds().
      This isn't really what it's for, but was how it worked before.
    modified:
      backend/render_handler.h
      backend/render_handler_agg.cpp
      backend/render_handler_cairo.cpp
      libcore/MorphShape.cpp
      libcore/MorphShape.h
      libcore/render.cpp
      libcore/render.h
      libcore/swf/DefineMorphShapeTag.cpp
      libcore/swf/ShapeRecord.cpp
      libcore/swf/ShapeRecord.h
    ------------------------------------------------------------
    revno: 10771.1.38
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 16:38:20 +0200
    message:
      Drop morph includes again.
    modified:
      backend/render_handler_cairo.cpp
    ------------------------------------------------------------
    revno: 10771.1.39
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-04-07 16:45:34 +0200
    message:
      Fix OGL build.
    modified:
      backend/render_handler_ogl.cpp
      backend/render_handler_ogl.h
=== modified file 'backend/Makefile.am'
--- a/backend/Makefile.am       2009-01-22 20:10:39 +0000
+++ b/backend/Makefile.am       2009-04-06 20:29:42 +0000
@@ -36,6 +36,7 @@
         -I$(top_srcdir)/libnet \
         -I$(top_srcdir)/libcore \
         -I$(top_srcdir)/libcore/parser \
+        -I$(top_srcdir)/libcore/swf \
         -I$(top_srcdir)/libbase \
        -I$(top_srcdir)/backend \
        $(PTHREAD_CFLAGS) \

=== modified file 'backend/PathParser.cpp'
--- a/backend/PathParser.cpp    2009-02-25 22:33:03 +0000
+++ b/backend/PathParser.cpp    2009-04-07 14:00:27 +0000
@@ -36,7 +36,7 @@
   return _fill_type == FILL_LEFT ? _path->m_edges.back().ap : _path->ap;
 }
 
-PathParser::PathParser(const std::vector<path>& paths, size_t numstyles)
+PathParser::PathParser(const std::vector<Path>& paths, size_t numstyles)
 : _paths(paths),
   _num_styles(numstyles),
   _shape_origin(0, 0),
@@ -54,7 +54,7 @@
 
   for (size_t i = 0; i < _paths.size(); ++i) {
   
-    if (_paths[i].is_empty()) {
+    if (_paths[i].empty()) {
       continue;
     }
 
@@ -129,9 +129,9 @@
                                                           this, _1));
   } else {
 
-    for (std::vector<edge>::const_reverse_iterator prev = edges.rbegin(),
+    for (std::vector<Edge>::const_reverse_iterator prev = edges.rbegin(),
          it = boost::next(prev), end = edges.rend(); it != end; ++it, ++prev) {
-      if ((*prev).isStraight()) {
+      if ((*prev).straight()) {
         lineTo((*it).ap);
       } else {
         line_to(Edge((*prev).cp, (*it).ap));
@@ -145,9 +145,9 @@
 }
 
 void
-PathParser::line_to(const edge& curve)
+PathParser::line_to(const Edge& curve)
 {
-  if (curve.isStraight()) {
+  if (curve.straight()) {
     lineTo(curve.ap);
   } else {
     curveTo(curve);

=== modified file 'backend/PathParser.h'
--- a/backend/PathParser.h      2009-03-11 13:41:02 +0000
+++ b/backend/PathParser.h      2009-04-07 14:00:27 +0000
@@ -39,7 +39,7 @@
   
   UnivocalPath() : _path(NULL), _fill_type(FILL_LEFT) {}
 
-  UnivocalPath(const path* path, fill_type filltype)
+  UnivocalPath(const Path* path, fill_type filltype)
     : _path(path),
       _fill_type(filltype)
   {
@@ -48,7 +48,7 @@
   const point& startPoint() const;
   const point& endPoint() const;
 
-  const path* _path;
+  const Path* _path;
   fill_type   _fill_type;
 };
 
@@ -62,7 +62,7 @@
 public:
   /// @param paths list of Flash paths to be 'parsed'.
   /// @param num_styles count of fill styles pointed to by the first argument.
-  PathParser(const std::vector<path>& paths, size_t num_styles);
+  PathParser(const std::vector<Path>& paths, size_t num_styles);
 
   virtual ~PathParser() { }
 
@@ -95,7 +95,7 @@
   virtual void moveTo(const point& p) = 0;
   
   /// Draw the given curve using the path pencil.
-  virtual void curveTo(const edge& curve) = 0;
+  virtual void curveTo(const Edge& curve) = 0;
 
   /// Draw a straight line to the given point.
   virtual void lineTo(const point& p) = 0;
@@ -113,9 +113,9 @@
   
   bool closed_shape();
 
-  void line_to(const edge& curve);
+  void line_to(const Edge& curve);
 
-  const std::vector<path>& _paths;
+  const std::vector<Path>& _paths;
   const size_t             _num_styles;
   point       _shape_origin;
   point       _cur_endpoint;

=== modified file 'backend/render_handler.h'
--- a/backend/render_handler.h  2009-04-03 09:18:40 +0000
+++ b/backend/render_handler.h  2009-04-07 14:32:06 +0000
@@ -146,7 +146,7 @@
 #include "dsodefs.h" // for DSOEXPORT
 
 #include "gnash.h" // Quality
-#include "shape_character_def.h"    
+#include "DefineShapeTag.h"    
 #include "DisplayObject.h"
 #include "Range2d.h"
 
@@ -158,7 +158,14 @@
     class SWFMatrix;
     class cxform;
 
-    class shape_character_def;
+    namespace SWF {
+        class DefineMorphShapeTag;
+        class ShapeRecord;
+    }
+    class DefineShapeTag;
+
+    class Shape;
+    class MorphShape;
 
     class GnashImage;
 }
@@ -283,38 +290,8 @@
         const rgba& fill, const rgba& outline, const SWFMatrix& mat,
         bool masked) = 0;
         
-        
-    /// \brief
-    /// Draws the given character definition with the stateful properties
-    /// of the given instance.
-    //
-    /// Normally this does not need to be re-implemented in 
-    /// render handler implementations. Instead, see the version without
-    /// character instance.
-    ///
-    virtual void drawShape(shape_character_def *def, DisplayObject *inst)
-    {
-        // check if the character needs to be rendered at all
-        rect cur_bounds;
-
-        cur_bounds.expand_to_transformed_rect(inst->getWorldMatrix(), 
-                def->get_bound());
-                
-        if (!bounds_in_clipping_area(cur_bounds))
-        {
-                return; // no need to draw
-        }        
-
-        // render the character
-        drawShape(def, inst->getWorldMatrix(),
-                inst->get_world_cxform());
-    }
-    
-    /// \brief
-    /// Draws the given character definition with the given transformations and
-    /// styles. 
-    virtual void drawShape(shape_character_def *def, 
-        const SWFMatrix& mat, const cxform& cx) = 0;
+    virtual void drawShape(const SWF::ShapeRecord& shape, const cxform& cx,
+            const SWFMatrix& worldMat) = 0;
         
     /// \brief
     /// Draws a glyph (font character).
@@ -330,8 +307,8 @@
     /// @param mat
     ///
     /// @param color
-    virtual void draw_glyph(shape_character_def *def, const SWFMatrix& mat,
-        const rgba& color) = 0;
+    virtual void drawGlyph(const SWF::ShapeRecord& rec, const rgba& color,
+           const SWFMatrix& mat) = 0;
 
 
     /// ==================================================================

=== modified file 'backend/render_handler_agg.cpp'
--- a/backend/render_handler_agg.cpp    2009-04-03 09:18:40 +0000
+++ b/backend/render_handler_agg.cpp    2009-04-07 14:32:06 +0000
@@ -120,8 +120,12 @@
 #include "render_handler.h"
 #include "render_handler_agg.h" 
 #include "Range2d.h"
-#include "shape_character_def.h" 
+#include "swf/DefineMorphShapeTag.h" 
+#include "swf/ShapeRecord.h" 
+#include "DefineShapeTag.h" 
 #include "DisplayObject.h"
+#include "MorphShape.h"
+#include "Shape.h"
 #include "GnashNumeric.h"
 
 #include <agg_rendering_buffer.h>
@@ -181,7 +185,7 @@
 typedef std::vector<agg::path_storage> AggPaths;
 typedef std::vector<geometry::Range2d<int> > ClipBounds;
 typedef std::vector<AlphaMask*> AlphaMasks;
-typedef std::vector<path> GnashPaths;
+typedef std::vector<Path> GnashPaths;
 
 template <class Rasterizer>
 inline void applyClipBox(Rasterizer& ras, const geometry::Range2d<int>& bounds)
@@ -209,7 +213,7 @@
 
     for (int pno=0; pno<pcount; ++pno) {
 
-        const path &the_path = paths[pno];
+        const Path &the_path = paths[pno];
 
         if ((the_path.m_fill0 > 0) || (the_path.m_fill1 > 0)) {
             have_shape = true;
@@ -233,9 +237,9 @@
         _shift(shift)
     {}
 
-    void operator()(const edge& edge)
+    void operator()(const Edge& edge)
     {
-        if (edge.is_straight()) {
+        if (edge.straight()) {
             _path.line_to(twipsToPixels(edge.ap.x) + _shift, 
                           twipsToPixels(edge.ap.y) + _shift);
         }
@@ -265,7 +269,7 @@
     {
     }
 
-    void operator()(const path& in)
+    void operator()(const Path& in)
     {
         agg::path_storage& p = *_it;
 
@@ -859,22 +863,20 @@
     }
   
 
-  void draw_glyph(shape_character_def *def,
-      const SWFMatrix& mat, const rgba& color) 
+  void drawGlyph(const SWF::ShapeRecord& shape, const rgba& color,
+          const SWFMatrix& mat) 
   {
     
     // select relevant clipping bounds
-    if (def->get_bound().is_null()) {
+    if (shape.getBounds().is_null()) {
         return;
-        // Why would we want to do this?
-        //select_all_clipbounds();  
     } 
-    else select_clipbounds(def, mat);
+    select_clipbounds(shape.getBounds(), mat);
     
     if (_clipbounds_selected.empty()) return; 
       
     GnashPaths paths;
-    apply_matrix_to_path(def->paths(), paths, mat);
+    apply_matrix_to_path(shape.paths(), paths, mat);
 
     // If it's a mask, we don't need the rest.
     if (m_drawing_mask) {
@@ -907,18 +909,16 @@
   /// rendering of characters outside a particular clipping range.
   /// "_clipbounds_selected" is used by draw_shape() and draw_outline() and
   /// *must* be initialized prior to using those function.
-  void select_clipbounds(const shape_character_def *def, 
-    const SWFMatrix& source_mat) {
+  void select_clipbounds(const rect& objectBounds, const SWFMatrix& source_mat)
+  {
     
     SWFMatrix mat = stage_matrix;
     mat.concatenate(source_mat);
   
     _clipbounds_selected.clear();
     _clipbounds_selected.reserve(_clipbounds.size());
-    
-    const rect& ch_bounds = def->get_bound();
 
-    if (ch_bounds.is_null()) {
+    if (objectBounds.is_null()) {
       log_debug(_("Warning: select_clipbounds encountered a character "
                   "definition with null bounds"));
       return;
@@ -926,7 +926,7 @@
 
     rect bounds;    
     bounds.set_null();
-    bounds.expand_to_transformed_rect(mat, ch_bounds);
+    bounds.expand_to_transformed_rect(mat, objectBounds);
     
     const geometry::Range2d<float>& range_float = bounds.getRange();
     
@@ -956,30 +956,54 @@
     _clipbounds_selected.clear();
     _clipbounds_selected.reserve(_clipbounds.size());
     
-    for (ClipBounds::const_iterator i = _clipbounds.begin(),
+    for (ClipBounds::iterator i = _clipbounds.begin(),
             e = _clipbounds.end(); i != e; ++i)
     {
       _clipbounds_selected.push_back(&(*i));
     }
   }
 
-    void drawShape(shape_character_def *def, 
-    const SWFMatrix& mat, const cxform& cx)
-    {
-    
-        const std::vector<fill_style>& fill_styles = def->fillStyles();
-        const std::vector<line_style>& line_styles = def->lineStyles();
+    void drawShape(const SWF::ShapeRecord& shape, const cxform& cx,
+            const SWFMatrix& worldMat)
+    {
+        // check if the character needs to be rendered at all
+        rect cur_bounds;
+
+        cur_bounds.expand_to_transformed_rect(worldMat, shape.getBounds());
+                
+        if (!render_handler::bounds_in_clipping_area(cur_bounds))
+        {
+            return; // no need to draw
+        }        
+        
+        const SWF::ShapeRecord::FillStyles& fillStyles = shape.fillStyles();
+        const SWF::ShapeRecord::LineStyles& lineStyles = shape.lineStyles();
+        const SWF::ShapeRecord::Paths& paths = shape.paths();
+        
+        // select ranges
+        select_clipbounds(shape.getBounds(), worldMat);
+
+        // render the DisplayObject's shape.
+        drawShape(fillStyles, lineStyles, paths, worldMat, cx);
+    }
+
+    void drawShape(const std::vector<fill_style>& fill_styles,
+        const std::vector<line_style>& line_styles,
+        const std::vector<Path>& objpaths, const SWFMatrix& mat,
+        const cxform& cx)
+    {
+
         bool have_shape, have_outline;
 
-        analyzePaths(def->paths(), have_shape, have_outline);
+        analyzePaths(objpaths, have_shape, have_outline);
 
         if (!have_shape && !have_outline) {
             // Early return for invisible character.
             return; 
-        }    
+        }        
 
         GnashPaths paths;
-        apply_matrix_to_path(def->paths(), paths, mat);
+        apply_matrix_to_path(objpaths, paths, mat);
 
         // Masks apparently do not use agg_paths, so return
         // early
@@ -991,21 +1015,19 @@
             return;
         }
 
-        AggPaths agg_paths;  
-        AggPaths agg_paths_rounded;  
+        AggPaths agg_paths;    
+        AggPaths agg_paths_rounded;    
 
         // Flash only aligns outlines. Probably this is done at rendering
         // level.
         if (have_outline) {
-            buildPaths_rounded(agg_paths_rounded, paths, line_styles);   
+            buildPaths_rounded(agg_paths_rounded, paths, line_styles);     
         }
 
         if (have_shape) {
             buildPaths(agg_paths, paths);
         }
         
-        // select ranges
-        select_clipbounds(def, mat);
 
         if (_clipbounds_selected.empty()) {
             log_debug(_("Warning: AGG renderer skipping a whole character"));
@@ -1022,9 +1044,9 @@
         for (unsigned int subshape=0; subshape<subshape_count; ++subshape)
         {
             if (have_shape) {
-                draw_shape(subshape, paths, agg_paths, sh, true);    
+                draw_shape(subshape, paths, agg_paths, sh, true);        
             }
-            if (have_outline)      {
+            if (have_outline)            {
                 draw_outlines(subshape, paths, agg_paths_rounded,
                         line_styles, cx, mat);
             }
@@ -1032,10 +1054,8 @@
 
         // Clear selected clipbounds to ease debugging 
         _clipbounds_selected.clear();
+    }
 
-    } // drawShape
-  
-  
     /// Takes a path and translates it using the given SWFMatrix. The new path
     /// is stored in paths_out. Both paths_in and paths_out are expected to
     /// be in TWIPS.
@@ -1054,7 +1074,7 @@
 
         /// Transform all the paths using the matrix.
         std::for_each(paths_out.begin(), paths_out.end(), 
-                boost::bind(&path::transform, _1, mat));
+                boost::bind(&Path::transform, _1, mat));
     } 
 
 
@@ -1068,7 +1088,7 @@
     const size_t pcnt = path_in.size();
     
     for (size_t pno=0; pno<pcnt; ++pno) {
-      const path& this_path = path_in[pno];
+      const Path& this_path = path_in[pno];
       
       if (this_path.m_new_shape)
         sscount++;
@@ -1106,7 +1126,7 @@
     
     for (size_t pno=0; pno<pcount; ++pno) {
       
-      const path& this_path = paths[pno];
+      const Path& this_path = paths[pno];
       agg::path_storage& new_path = dest[pno];
       
       bool hinting=false, closed=false, hairline=false;
@@ -1133,16 +1153,16 @@
 
       // avoid extra edge when doing implicit close later
       if (closed && ecount && 
-        this_path.m_edges.back().is_straight()) --ecount;  
+        this_path.m_edges.back().straight()) --ecount;  
       
       for (size_t eno=0; eno<ecount; ++eno) {
         
-        const edge& this_edge = this_path.m_edges[eno];
+        const Edge& this_edge = this_path.m_edges[eno];
         
         float this_ax = twipsToPixels(this_edge.ap.x);  
         float this_ay = twipsToPixels(this_edge.ap.y);  
         
-        if (hinting || this_edge.is_straight()) {
+        if (hinting || this_edge.straight()) {
         
           // candidate for alignment?
           bool align_x = hinting || (hairline && (prev_ax == this_ax));
@@ -1450,7 +1470,7 @@
   
       for (size_t pno=0; pno<pcount; ++pno) {
           
-        const path &this_path_gnash = paths[pno];
+        const Path &this_path_gnash = paths[pno];
         agg::path_storage &this_path_agg = 
           const_cast<agg::path_storage&>(agg_paths[pno]);
         
@@ -1490,7 +1510,7 @@
 
   // very similar to draw_shape but used for generating masks. There are no
   // fill styles nor subshapes and such. Just render plain solid shapes.
-  void draw_mask_shape(const GnashPaths &paths, bool even_odd)
+  void draw_mask_shape(const GnashPaths& paths, bool even_odd)
   {
 
     const AlphaMasks::size_type mask_count = _alphaMasks.size();
@@ -1523,7 +1543,7 @@
   
   
   template <class scanline_type>
-  void draw_mask_shape_impl(const GnashPaths &paths, bool even_odd,
+  void draw_mask_shape_impl(const GnashPaths& paths, bool even_odd,
     scanline_type& sl) {
     
     typedef agg::pixfmt_gray8 pixfmt;
@@ -1665,7 +1685,7 @@
 
       for (size_t pno=0, pcount=paths.size(); pno<pcount; ++pno) {
 
-        const path& this_path_gnash = paths[pno];
+        const Path& this_path_gnash = paths[pno];
 
         agg::path_storage &this_path_agg = 
           const_cast<agg::path_storage&>(agg_paths[pno]);

=== modified file 'backend/render_handler_cairo.cpp'
--- a/backend/render_handler_cairo.cpp  2009-04-03 09:18:40 +0000
+++ b/backend/render_handler_cairo.cpp  2009-04-07 14:38:20 +0000
@@ -40,6 +40,7 @@
 #include "GnashImage.h"
 #include <cmath>
 #include "PathParser.h"
+#include "swf/ShapeRecord.h"
 
 namespace gnash {
 
@@ -286,7 +287,7 @@
 class CairoPathRunner : public PathParser
 {
 public:
-  CairoPathRunner(const std::vector<path>& paths,
+  CairoPathRunner(const std::vector<Path>& paths,
                   const std::vector<fill_style>& fill_styles, cairo_t* context)
   : PathParser(paths, fill_styles.size()),
     _cr(context),
@@ -329,7 +330,7 @@
       cairo_move_to(_cr, x, y);
   }
 
-  virtual void curveTo(const edge& cur_edge)
+  virtual void curveTo(const Edge& cur_edge)
   {
     const float two_thirds = 2.0/3.0;
     const float one_third = 1 - two_thirds;
@@ -403,8 +404,8 @@
 
 class DSOEXPORT render_handler_cairo: public render_handler
 {
-  typedef std::vector<path> PathVec;
-  typedef std::vector<const path*> PathPtrVec;
+  typedef std::vector<Path> PathVec;
+  typedef std::vector<const Path*> PathPtrVec;
 public:
 
   render_handler_cairo()
@@ -740,7 +741,7 @@
     _masks.pop_back();
   }
 
-  void add_path(cairo_t* cr, const path& cur_path)
+  void add_path(cairo_t* cr, const Path& cur_path)
   {  
     double x = cur_path.ap.x;
     double y = cur_path.ap.y;
@@ -748,11 +749,11 @@
     snap_to_half_pixel(cr, x, y);
     cairo_move_to(cr, x, y);
     
-    for (std::vector<edge>::const_iterator it = cur_path.m_edges.begin(),
+    for (std::vector<Edge>::const_iterator it = cur_path.m_edges.begin(),
          end = cur_path.m_edges.end(); it != end; ++it) {
-      const edge& cur_edge = *it;
+      const Edge& cur_edge = *it;
       
-      if (cur_edge.is_straight()) {
+      if (cur_edge.straight()) {
         x = cur_edge.ap.x;
         y = cur_edge.ap.y;
         snap_to_half_pixel(cr, x, y);
@@ -852,7 +853,7 @@
   {  
     for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
          it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
       if (!cur_path.m_line) {
         continue;
       }
@@ -889,7 +890,7 @@
     ++it;
 
     for (;it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
          
            if (cur_path.m_new_shape) {
              subshapes.push_back(it); 
@@ -905,7 +906,7 @@
   {    
     for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
          it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
       
       if (cur_path.m_fill0 || cur_path.m_fill1) {
         _masks.back().push_back(cur_path);     
@@ -918,7 +919,7 @@
   {
     for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
          it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
       
       add_path(_cr, cur_path);
     }  
@@ -926,18 +927,17 @@
 
   /// Takes a path and translates it using the given SWFMatrix.
   void
-  apply_matrix_to_paths(std::vector<path>& paths, const SWFMatrix& mat)
+  apply_matrix_to_paths(std::vector<Path>& paths, const SWFMatrix& mat)
   {  
     std::for_each(paths.begin(), paths.end(),
-                  boost::bind(&path::transform, _1, boost::ref(mat)));
+                  boost::bind(&Path::transform, _1, boost::ref(mat)));
   }
-                  
-  virtual void drawShape(shape_character_def *def, 
-    const SWFMatrix& mat,
-    const cxform& cx)
+  
+  virtual void drawShape(const SWF::ShapeRecord& shape, const cxform& cx,
+        const SWFMatrix& mat)
   {
         
-    const PathVec& path_vec = def->paths();
+    const PathVec& path_vec = shape.paths();
     
     if (!path_vec.size()) {
       return;    
@@ -957,8 +957,8 @@
 
     std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
     
-    const std::vector<fill_style>& fill_styles = def->fillStyles();
-    const std::vector<line_style>& line_styles = def->lineStyles();
+    const std::vector<fill_style>& fill_styles = shape.fillStyles();
+    const std::vector<line_style>& line_styles = shape.lineStyles();
 
     for (size_t i = 0; i < subshapes.size()-1; ++i) {
       PathVec subshape_paths;
@@ -975,8 +975,8 @@
     
   }
   
-  virtual void draw_glyph(shape_character_def *def, const SWFMatrix& mat,
-    const rgba& color)
+  virtual void drawGlyph(const SWF::ShapeRecord& rec, const rgba& color,
+         const SWFMatrix& mat)
   {
   
     cxform dummy_cx;
@@ -987,7 +987,7 @@
     
     glyph_fs.push_back(coloring);
     
-    const PathVec& path_vec = def->paths();
+    const PathVec& path_vec = rec.paths();
     
     std::vector<line_style> dummy_ls;
     

=== modified file 'backend/render_handler_ogl.cpp'
--- a/backend/render_handler_ogl.cpp    2009-04-03 09:18:40 +0000
+++ b/backend/render_handler_ogl.cpp    2009-04-07 14:45:34 +0000
@@ -24,7 +24,7 @@
 #include <cmath>
 
 #include "render_handler.h"
-
+#include "swf/ShapeRecord.h"
 #include "gnash.h"
 #include "RGBA.h"
 #include "GnashImage.h"
@@ -168,7 +168,7 @@
 #endif // OSMESA_TESTING
 
 
-typedef std::vector<path> PathVec;
+typedef std::vector<Path> PathVec;
 
 class oglScopeEnable : public boost::noncopyable
 {
@@ -290,21 +290,21 @@
 
 
 
-std::vector<oglVertex> interpolate(const std::vector<edge>& edges, const 
float& anchor_x,
-                                   const float& anchor_y)
+std::vector<oglVertex> interpolate(const std::vector<Edge>& edges,
+        const float& anchor_x, const float& anchor_y)
 {
   point anchor(anchor_x, anchor_y);
   
   std::vector<oglVertex> shape_points;
   shape_points.push_back(oglVertex(anchor));
   
-  for (std::vector<edge>::const_iterator it = edges.begin(), end = edges.end();
+  for (std::vector<Edge>::const_iterator it = edges.begin(), end = edges.end();
         it != end; ++it) {
-      const edge& the_edge = *it;
+      const Edge& the_edge = *it;
       
       point target(the_edge.ap.x, the_edge.ap.y);
 
-      if (the_edge.is_straight()) {
+      if (the_edge.straight()) {
         shape_points.push_back(oglVertex(target));
       } else {
         point control(the_edge.cp.x, the_edge.cp.y);
@@ -1032,7 +1032,7 @@
   }
 
 #if 0
-  void print_path(const path& path)
+  void print_path(const Path& path)
   {
     std::cout << "Origin: ("
               << path.ap.x
@@ -1064,28 +1064,28 @@
 #endif
   
   
-  path reverse_path(const path& cur_path)
+  Path reverse_path(const Path& cur_path)
   {
-    const edge& cur_end = cur_path.m_edges.back();    
+    const Edge& cur_end = cur_path.m_edges.back();    
         
     float prev_cx = cur_end.cp.x;
     float prev_cy = cur_end.cp.y;        
                 
-    path newpath(cur_end.ap.x, cur_end.ap.y, cur_path.m_fill1, 
cur_path.m_fill0, cur_path.m_line, cur_path.m_new_shape);
+    Path newpath(cur_end.ap.x, cur_end.ap.y, cur_path.m_fill1, 
cur_path.m_fill0, cur_path.m_line, cur_path.m_new_shape);
     
     float prev_ax = cur_end.ap.x;
     float prev_ay = cur_end.ap.y; 
 
-    for (std::vector<edge>::const_reverse_iterator it = 
cur_path.m_edges.rbegin()+1, end = cur_path.m_edges.rend();
+    for (std::vector<Edge>::const_reverse_iterator it = 
cur_path.m_edges.rbegin()+1, end = cur_path.m_edges.rend();
          it != end; ++it) {
-      const edge& cur_edge = *it;
+      const Edge& cur_edge = *it;
 
       if (prev_ax == prev_cx && prev_ay == prev_cy) {
         prev_cx = cur_edge.ap.x;
         prev_cy = cur_edge.ap.y;      
       }
 
-      edge newedge(prev_cx, prev_cy, cur_edge.ap.x, cur_edge.ap.y); 
+      Edge newedge(prev_cx, prev_cy, cur_edge.ap.x, cur_edge.ap.y); 
           
       newpath.m_edges.push_back(newedge);
           
@@ -1096,14 +1096,14 @@
            
     }
         
-    edge newlastedge(prev_cx, prev_cy, cur_path.ap.x, cur_path.ap.y);    
+    Edge newlastedge(prev_cx, prev_cy, cur_path.ap.x, cur_path.ap.y);    
     newpath.m_edges.push_back(newlastedge);
         
     return newpath;
   }
   
-  const path* find_connecting_path(const path& to_connect,
-                                   std::list<const path*> path_refs)
+  const Path* find_connecting_path(const Path& to_connect,
+                                   std::list<const Path*> path_refs)
   {
         
     float target_x = to_connect.m_edges.back().ap.x;
@@ -1114,9 +1114,9 @@
       return NULL;
     }
   
-    for (std::list<const path*>::const_iterator it = path_refs.begin(), end = 
path_refs.end();
+    for (std::list<const Path*>::const_iterator it = path_refs.begin(), end = 
path_refs.end();
          it != end; ++it) {
-      const path* cur_path = *it;
+      const Path* cur_path = *it;
       
       if (cur_path == &to_connect) {
       
@@ -1144,7 +1144,7 @@
   
     for (PathVec::const_iterator it = paths.begin(), end = paths.end();
          it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
       
       if (cur_path.m_edges.empty()) {
         continue;
@@ -1155,14 +1155,14 @@
         normalized.push_back(cur_path);
         normalized.back().m_fill0 = 0; 
      
-        path newpath = reverse_path(cur_path);
+        Path newpath = reverse_path(cur_path);
         newpath.m_fill0 = 0;        
            
         normalized.push_back(newpath);       
 
       } else if (cur_path.m_fill0) {
         // Left fill style.
-        path newpath = reverse_path(cur_path);
+        Path newpath = reverse_path(cur_path);
         newpath.m_fill0 = 0;
            
         normalized.push_back(newpath);
@@ -1198,7 +1198,7 @@
     
     for (int pno=0; pno<pcount; pno++) {
     
-      const path &the_path = paths[pno];
+      const Path &the_path = paths[pno];
     
       if ((the_path.m_fill0>0) || (the_path.m_fill1>0)) {
         have_shape=true;
@@ -1347,7 +1347,7 @@
     
     for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
          it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
 
       if (!cur_path.m_edges.size()) {
         continue;
@@ -1361,10 +1361,10 @@
     return pathpoints;
   } 
   
-  typedef std::vector<const path*> PathPtrVec;
+  typedef std::vector<const Path*> PathPtrVec;
   
   static void
-  draw_point(const edge& point_edge)
+  draw_point(const Edge& point_edge)
   {  
     glVertex2d(point_edge.ap.x, point_edge.ap.y);  
   }
@@ -1377,7 +1377,7 @@
   
     for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
          it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
       
       if (!cur_path.m_line) {
         continue;
@@ -1415,19 +1415,19 @@
 
   std::list<PathPtrVec> get_contours(const PathPtrVec &paths)
   {
-    std::list<const path*> path_refs;
+    std::list<const Path*> path_refs;
     std::list<PathPtrVec> contours;
     
     
     for (PathPtrVec::const_iterator it = paths.begin(), end = paths.end();
          it != end; ++it) {
-      const path* cur_path = *it;
+      const Path* cur_path = *it;
       path_refs.push_back(cur_path);
     }
         
-    for (std::list<const path*>::const_iterator it = path_refs.begin(), end = 
path_refs.end();
+    for (std::list<const Path*>::const_iterator it = path_refs.begin(), end = 
path_refs.end();
          it != end; ++it) {
-      const path* cur_path = *it;
+      const Path* cur_path = *it;
       
       if (cur_path->m_edges.empty()) {
         continue;
@@ -1441,13 +1441,13 @@
             
       contour.push_back(cur_path);
         
-      const path* connector = find_connecting_path(*cur_path, path_refs);
+      const Path* connector = find_connecting_path(*cur_path, path_refs);
 
       while (connector) {       
         contour.push_back(connector);
 
-        const path* tmp = connector;
-        connector = find_connecting_path(*connector, std::list<const 
path*>(boost::next(it), end));
+        const Path* tmp = connector;
+        connector = find_connecting_path(*connector, std::list<const 
Path*>(boost::next(it), end));
   
         // make sure we don't iterate over the connecting path in the for loop.
         path_refs.remove(tmp);
@@ -1465,7 +1465,7 @@
   {    
     for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
          it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
       
       if (cur_path.m_fill0 || cur_path.m_fill1) {
         _masks.back().push_back(cur_path);
@@ -1480,7 +1480,7 @@
     PathPtrVec paths;
     for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
          it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
       
       if (cur_path.m_fill0 == style) {
         paths.push_back(&cur_path);
@@ -1507,7 +1507,7 @@
     ++it;
 
     for (;it != end; ++it) {
-      const path& cur_path = *it;
+      const Path& cur_path = *it;
     
       if (cur_path.m_new_shape) {
         subshapes.push_back(it); 
@@ -1523,10 +1523,10 @@
   
   /// Takes a path and translates it using the given SWFMatrix.
   void
-  apply_matrix_to_paths(std::vector<path>& paths, const SWFMatrix& mat)
+  apply_matrix_to_paths(std::vector<Path>& paths, const SWFMatrix& mat)
   {  
     std::for_each(paths.begin(), paths.end(),
-                  boost::bind(&path::transform, _1, boost::ref(mat)));
+                  boost::bind(&Path::transform, _1, boost::ref(mat)));
                   
     //for_each(paths, &path::transform, mat);
   }  
@@ -1560,7 +1560,7 @@
                    
         for (PathPtrVec::const_iterator it = refs.begin(), end = refs.end();
              it != end; ++it) {
-          const path& cur_path = *(*it);          
+          const Path& cur_path = *(*it);          
           
           assert(pathpoints.find(&cur_path) != pathpoints.end());
 
@@ -1607,11 +1607,11 @@
 // 5. Profit!
 
   virtual void
-  drawShape(shape_character_def *def, const SWFMatrix& mat,
-    const cxform& cx)
+  drawShape(const SWF::ShapeRecord& shape, const cxform& cx,
+          const SWFMatrix& mat)
   {
   
-    const PathVec& path_vec = def->paths();
+    const PathVec& path_vec = shape.paths();
 
     if (!path_vec.size()) {
       // No paths. Nothing to draw...
@@ -1638,8 +1638,8 @@
 
     std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
     
-    const std::vector<fill_style>& fill_styles = def->fillStyles();
-    const std::vector<line_style>& line_styles = def->lineStyles();
+    const std::vector<fill_style>& fill_styles = shape.fillStyles();
+    const std::vector<line_style>& line_styles = shape.lineStyles();
     
     for (size_t i = 0; i < subshapes.size()-1; ++i) {
       PathVec subshape_paths;
@@ -1655,8 +1655,8 @@
     }
   }
 
-  virtual void draw_glyph(shape_character_def *def, const SWFMatrix& mat,
-    const rgba& c)
+  virtual void drawGlyph(const SWF::ShapeRecord& rec, const rgba& c,
+         const SWFMatrix& mat)
   {
     if (_drawing_mask) abort();
     cxform dummy_cx;
@@ -1671,7 +1671,7 @@
     
     oglScopeMatrix scope_mat(mat);
     
-    draw_subshape(def->paths(), mat, dummy_cx, glyph_fs, dummy_ls);
+    draw_subshape(rec.paths(), mat, dummy_cx, glyph_fs, dummy_ls);
   }
 
   virtual void set_scale(float xscale, float yscale) {

=== modified file 'backend/render_handler_ogl.h'
--- a/backend/render_handler_ogl.h      2009-01-22 20:10:39 +0000
+++ b/backend/render_handler_ogl.h      2009-04-07 14:45:34 +0000
@@ -56,7 +56,7 @@
 
 
 
-typedef std::vector<const path*> PathRefs;
+typedef std::vector<const Path*> PathRefs;
 
 
 
@@ -76,7 +76,7 @@
   GLdouble _z;
 };
 
-typedef std::map< const path*, std::vector<oglVertex> > PathPointMap;
+typedef std::map<const Path*, std::vector<oglVertex> > PathPointMap;
 
 class Tesselator
 {
@@ -111,7 +111,7 @@
 class WholeShape
 {
 public:
-  void newPath(const path& new_path)
+  void newPath(const Path& new_path)
   {
     PathRefs refs;
     refs.push_back(&new_path);
@@ -119,7 +119,7 @@
     shape.push_back(refs);
   }
   
-  void addPath(const path& add_path)
+  void addPath(const Path& add_path)
   {
     PathRefs& refs = shape.back();
     refs.push_back(&add_path);

=== modified file 'cygnal/Makefile.am'
--- a/cygnal/Makefile.am        2009-03-19 23:14:43 +0000
+++ b/cygnal/Makefile.am        2009-04-06 20:29:42 +0000
@@ -56,6 +56,7 @@
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/libcore \
         -I$(top_srcdir)/libcore/asobj \
+        -I$(top_srcdir)/libcore/swf \
         -I$(top_srcdir)/libcore/parser \
         -I$(top_srcdir)/libcore/vm \
         -DLOCALEDIR=\"$(localedir)\" \

=== modified file 'gui/Makefile.am'
--- a/gui/Makefile.am   2009-02-27 06:46:40 +0000
+++ b/gui/Makefile.am   2009-04-06 20:29:42 +0000
@@ -37,6 +37,7 @@
         -I$(top_srcdir)/libamf \
         -I$(top_srcdir)/libnet \
         -I$(top_srcdir)/libcore \
+        -I$(top_srcdir)/libcore/swf \
         -I$(top_srcdir)/libcore/parser \
         -I$(top_srcdir)/libcore/vm \
        -I$(top_srcdir)/libltdl \

=== modified file 'libcore/Bitmap.cpp'
--- a/libcore/Bitmap.cpp        2009-04-03 09:18:40 +0000
+++ b/libcore/Bitmap.cpp        2009-04-07 09:19:54 +0000
@@ -30,11 +30,10 @@
     DisplayObject(parent, id),
     _bitmapData(bd),
     _bitmapInfo(0),
-    _shapeDef(new DynamicShape),
     _width(_bitmapData->getWidth()),
     _height(_bitmapData->getHeight())
 {
-    _shapeDef->set_bound(rect(0, 0, _width * 20, _height * 20));
+    _shape.setBounds(rect(0, 0, _width * 20, _height * 20));
 }
 
 
@@ -61,9 +60,7 @@
 void
 Bitmap::display()
 {
-    assert(_shapeDef);
-
-    _shapeDef->display(this);
+    _shape.display(*this);
 
     clear_invalidated();
 }
@@ -84,7 +81,7 @@
 rect
 Bitmap::getBounds() const
 {
-    return _shapeDef->get_bound();
+    return _shape.getBounds();
 }
 
 void
@@ -126,7 +123,7 @@
     /// set _bitmapData to 0 to avoid any further interaction.
     if (data.empty()) {
         _bitmapData = 0;
-        _shapeDef->set_bound(rect());
+        _shape.clear();
         return;
     }
 
@@ -137,24 +134,21 @@
     const int w = _width * 20;
     const int h = _height * 20;
 
-    if (!_shapeDef) {
-    }
-
     SWFMatrix mat;
     mat.set_scale(1.0 / 20, 1.0 / 20);
     fill_style fill(_bitmapInfo.get(), mat);
-    const size_t fillLeft = _shapeDef->add_fill_style(fill);
-
-
-    path bmpath(w, h, fillLeft, 0, 0, false);
+    const size_t fillLeft = _shape.add_fill_style(fill);
+
+
+    Path bmpath(w, h, fillLeft, 0, 0, false);
     bmpath.drawLineTo(w, 0);
     bmpath.drawLineTo(0, 0);
     bmpath.drawLineTo(0, h);
     bmpath.drawLineTo(w, h);
 
-    _shapeDef->add_path(bmpath);
+    _shape.add_path(bmpath);
 
-    _shapeDef->finalize();
+    _shape.finalize();
 
 }
 

=== modified file 'libcore/Bitmap.h'
--- a/libcore/Bitmap.h  2009-04-03 09:18:40 +0000
+++ b/libcore/Bitmap.h  2009-04-07 12:34:43 +0000
@@ -54,15 +54,9 @@
 
 protected:
 
-    /// This should really have an optional definition.
-    virtual character_def* getDefinition() const {
-        return _shapeDef.get();
-    }
-
     void markReachableObjects() const {
         if (_bitmapData) _bitmapData->setReachable();
         if (_bitmapInfo) _bitmapInfo->setReachable();
-        if (_shapeDef) _shapeDef->setReachable();
     }
 
 private:
@@ -80,8 +74,8 @@
     /// The current bitmap information is stored here.
     boost::intrusive_ptr<BitmapInfo> _bitmapInfo;
 
-    /// FIXME: using shape_character_def is unpleasant.
-    boost::intrusive_ptr<DynamicShape> _shapeDef;
+    /// FIXME: using DefineShapeTag is unpleasant.
+    DynamicShape _shape;
 
     /// This is cached to save querying the BitmapData often
     size_t _width;

=== modified file 'libcore/BitmapMovieInstance.cpp'
--- a/libcore/BitmapMovieInstance.cpp   2009-04-03 09:48:13 +0000
+++ b/libcore/BitmapMovieInstance.cpp   2009-04-07 09:19:54 +0000
@@ -31,10 +31,8 @@
        // We need to assign a DisplayObject id to the instance, or an assertion
        // will fail in DisplayObject.cpp (parent==NULL || id != -1)
 
-       character_def* chdef = def->get_character_def(1); 
-       assert(chdef);
-       boost::intrusive_ptr<DisplayObject> ch = 
-        chdef->createDisplayObject(this, 1);
+       assert(def);
+       boost::intrusive_ptr<DisplayObject> ch = def->createDisplayObject(this, 
1);
        
        const int depth = 1 + DisplayObject::staticDepthOffset;
        placeDisplayObject(ch.get(), depth);

=== modified file 'libcore/Button.cpp'
--- a/libcore/Button.cpp        2009-04-05 07:43:04 +0000
+++ b/libcore/Button.cpp        2009-04-07 12:34:43 +0000
@@ -735,7 +735,7 @@
                     DisplayObject::staticDepthOffset + 1;
                 int ch_id = bdef._id;
 
-                DisplayObject* ch = bdef.m_character_def->createDisplayObject(
+                DisplayObject* ch = bdef.m_DefinitionTag->createDisplayObject(
                         this, ch_id);
                 ch->setMatrix(mat, true); // update caches
                 ch->set_cxform(cx); 
@@ -898,7 +898,7 @@
         int ch_id = bdef._id;
 
         DisplayObject* ch =
-            bdef.m_character_def->createDisplayObject(this, ch_id);
+            bdef.m_DefinitionTag->createDisplayObject(this, ch_id);
         ch->setMatrix(mat, true);  // update caches
     
         // TODO: who cares about color, depth etc.
@@ -931,7 +931,7 @@
         int ch_depth = bdef.m_button_layer+DisplayObject::staticDepthOffset+1;
         int ch_id = bdef._id;
 
-        DisplayObject* ch = bdef.m_character_def->createDisplayObject(
+        DisplayObject* ch = bdef.m_DefinitionTag->createDisplayObject(
                 this, ch_id);
         ch->setMatrix(mat, true);  // update caches
         ch->set_cxform(cx); 

=== modified file 'libcore/DisplayObject.h'
--- a/libcore/DisplayObject.h   2009-04-05 07:43:04 +0000
+++ b/libcore/DisplayObject.h   2009-04-07 13:13:16 +0000
@@ -16,14 +16,13 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 
-#ifndef GNASH_CHARACTER_H
-#define GNASH_CHARACTER_H
+#ifndef GNASH_DISPLAY_OBJECT_H
+#define GNASH_DISPLAY_OBJECT_H
 
 #ifdef HAVE_CONFIG_H
 #include "gnashconfig.h" // USE_SWFTREE
 #endif
 
-#include "character_def.h"
 #include "smart_ptr.h" // GNASH_USE_GC
 #include "event_id.h" // for inlines
 #include "as_object.h" // for inheritance
@@ -67,9 +66,21 @@
 //
 /// Derived classes include InteractiveObject, StaticText, Bitmap,
 /// Video, and Shape.
+//
+/// All DisplayObjects may be constructed during SWF parsing. In this case
+/// they are constructed using an immutable, non-copyable SWF::DefinitionTag. 
+/// This tag should never be changed!
+//
+/// Most DisplayObjects may also be constructed dynamically. In AS3, Bitmaps
+/// and Shapes can be dynamically created. Dynamically-created DisplayObjects
+/// must not have a SWF::DefinitionTag!
+//
+/// The presence of a definition tag may be used to distinguish static from
+/// dynamic DisplayObjects, but tags are not always stored. They are not
+/// stored in most InteractiveObjects because most properties can be
+/// overridden during SWF execution.
 class DisplayObject : public as_object
 {
-
 public:
 
     DisplayObject(DisplayObject* parent, int id);

=== modified file 'libcore/DynamicShape.cpp'
--- a/libcore/DynamicShape.cpp  2009-03-12 07:54:13 +0000
+++ b/libcore/DynamicShape.cpp  2009-04-07 13:26:18 +0000
@@ -15,47 +15,43 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-
-
-
 #include "DynamicShape.h"
-
-#include <algorithm>
-
+#include "render.h"
+
+#include <vector>
 
 namespace gnash {
 
 DynamicShape::DynamicShape()
        :
-       shape_character_def(),
        _currpath(0),
        _currfill(0),
        _currline(0),
        _x(0),
        _y(0),
-       _changed(0)
+       _changed(false)
 {}
 
 void
 DynamicShape::clear()
 {
-       //clear_meshes();
-       _paths.clear();
-       _fill_styles.clear();
-       _line_styles.clear();
-       _bound.set_null();
-       _currpath=0; // or would point to invalid memory
-       _currfill = _currline = 0; // or would point to cleared m_fill_style 
and m_line_styles respectively
-
+       _shape.clear();
+       _currpath = 0; 
+       _currfill = _currline = 0; 
        // TODO: worth setting _changed=true ? 
 }
 
 void
-DynamicShape::add_path(const path& pth)
-{
-       _paths.push_back(pth);
-       _currpath = &(_paths.back());
-       //compute_bound(&m_bound);
+DynamicShape::display(const DisplayObject& inst)
+{
+    render::drawShape(_shape, inst.get_world_cxform(), inst.getWorldMatrix());
+}
+
+void
+DynamicShape::add_path(const Path& pth)
+{
+       _shape.addPath(pth);
+       _currpath = &_shape.currentPath();
 }
 
 void
@@ -86,7 +82,7 @@
        // TODO: how to know wheter the fill should be set
        //       as *left* or *right* fill ?
        //       A quick test shows that *left* always work fine !
-       path newPath(_x, _y, _currfill, 0, _currline, true); // new fill start 
new subshapes
+       Path newPath(_x, _y, _currfill, 0, _currline, true); // new fill start 
new subshapes
        add_path(newPath);
 }
 
@@ -102,7 +98,7 @@
        // TODO: how to know wheter the fill should be set
        //       as *left* or *right* fill ?
        //       A quick test shows that *left* always work fine !
-       path newPath(_x, _y, _currfill, 0, _currline, true); // new fill start 
new subshapes
+       Path newPath(_x, _y, _currfill, 0, _currline, true); // new fill start 
new subshapes
        add_path(newPath);
 }
 
@@ -118,7 +114,7 @@
        // TODO: how to know wheter the fill should be set
        //       as *left* or *right* fill ?
        //       A quick test shows that *left* always work fine !
-       path newPath(_x, _y, _currfill, 0, _currline, true); // new fill start 
new subshapes
+       Path newPath(_x, _y, _currfill, 0, _currline, true); 
        add_path(newPath);
 }
 
@@ -128,18 +124,17 @@
        // Close any pending filled path
        if ( _currpath && _currfill) _currpath->close();
 
-       // The DrawingApiTest.swf file shows we should NOT
-       // necessarely end the current fill when starting a new one.
-       //endFill();
+       // The DrawingApiTest.swf file shows we should not
+       // end the current fill when starting a new one.
 
        // A quick test shows that *left* always work fine !
        // More than that, using a *right* fill seems to break the tests !
-       path newPath(_x, _y, _currfill, 0, _currline, newShape);
+       Path newPath(_x, _y, _currfill, 0, _currline, newShape);
        add_path(newPath);
 }
 
 void
-DynamicShape::finalize()
+DynamicShape::finalize() const
 {
        // Nothing to do if not changed
        if ( ! _changed ) return;
@@ -147,8 +142,8 @@
        // Close any pending filled path (_currpath should be last path)
        if ( _currpath && _currfill)
        {
-               assert(!_paths.empty());
-               assert(_currpath == &(_paths.back()));
+               assert(!_shape.paths().empty());
+               assert(_currpath == &(_shape.paths().back()));
                _currpath->close();
        }
 
@@ -200,19 +195,24 @@
        _currpath->drawLineTo(x, y);
 
        // Update bounds 
-       unsigned thickness = _currline ? 
_line_styles[_currline-1].getThickness() : 0;
+    rect bounds = _shape.getBounds();
+
+       unsigned thickness = _currline ? 
+        _shape.lineStyles()[_currline-1].getThickness() : 0;
        if ( _currpath->size() == 1 ) {
-               _currpath->expandBounds(_bound, thickness, swfVersion);
+               _currpath->expandBounds(bounds, thickness, swfVersion);
        } else {
-               _bound.expand_to_circle(x, y, swfVersion < 8 ? thickness : 
thickness/2.0);
+               bounds.expand_to_circle(x, y, swfVersion < 8 ? thickness : 
thickness/2.0);
        }
     
+    _shape.setBounds(bounds);
+
        // Update current pen position
        _x = x;
        _y = y;
 
        // Mark as changed
-       changed();
+       _changed = true;
 }
 
 void
@@ -224,46 +224,42 @@
 
        _currpath->drawCurveTo(cx, cy, ax, ay);
 
-       // Update bounds 
-       unsigned thickness = _currline ? 
_line_styles[_currline-1].getThickness() : 0;
+    rect bounds = _shape.getBounds();
+
+       unsigned thickness = _currline ? 
+        _shape.lineStyles()[_currline-1].getThickness() : 0;
        if ( _currpath->size() == 1 ) {
-               _currpath->expandBounds(_bound, thickness, swfVersion);
+               _currpath->expandBounds(bounds, thickness, swfVersion);
        }
     else {
-               _bound.expand_to_circle(ax, ay, 
+               bounds.expand_to_circle(ax, ay, 
                 swfVersion < 8 ? thickness : thickness/2.0);
-               _bound.expand_to_circle(cx, cy,
+               bounds.expand_to_circle(cx, cy,
                 swfVersion < 8 ? thickness : thickness/2.0);
     }
 
+    _shape.setBounds(bounds);
+
        // Update current pen position
        _x = ax;
        _y = ay;
 
        // Mark as changed
-       changed();
+       _changed = true;
 }
 
 size_t
 DynamicShape::add_fill_style(const fill_style& stl)
 {
-       FillStyles& v = _fill_styles;
-
-       // TODO: check if the style is already in our list
-       //       (needs operator== defined for fill_style)
-       v.push_back(stl);
-       return v.size(); // 1-based !
+    _shape.addFillStyle(stl);
+    return _shape.fillStyles().size();
 }
 
 size_t
 DynamicShape::add_line_style(const line_style& stl)
 {
-       LineStyles& v = _line_styles;
-
-       // TODO: check if the style is already in our list
-       //       (needs operator== defined for line_style)
-       v.push_back(stl);
-       return v.size(); // 1-based !
+    _shape.addLineStyle(stl);
+    return _shape.lineStyles().size();
 }
        
 }      // end namespace gnash

=== modified file 'libcore/DynamicShape.h'
--- a/libcore/DynamicShape.h    2009-02-25 22:33:03 +0000
+++ b/libcore/DynamicShape.h    2009-04-07 12:34:43 +0000
@@ -20,26 +20,30 @@
 #ifndef GNASH_DYNAMIC_SHAPE_H
 #define GNASH_DYNAMIC_SHAPE_H
 
-#include "shape_character_def.h"  // for inheritance
-#include "styles.h" // for cap_style_e and join_style_e enums
-
+#include "fill_style.h"
+#include "styles.h" 
+#include "swf/ShapeRecord.h"
 
 namespace gnash {
-    class fill_style;
+    class DisplayObject;
 }
 
 namespace gnash {
 
-/// \brief
-/// Represents the outline of one or more shapes, along with
-/// information on fill and line styles.
-class DynamicShape : public shape_character_def
+/// The DynamicShape class represents a mutable shape.
+//
+/// It is provides mutating functions for the SWF::ShapeRecord class that
+/// are used in the Flash drawing API.
+//
+/// DynamicShape objects are not refcounted, so must be stack-allocated or
+/// wrapped in smart pointers.
+class DynamicShape
 {
 public:
 
        DynamicShape();
 
-       virtual ~DynamicShape() {}
+       ~DynamicShape() {}
 
        /// Remove all paths and style informations
        void clear();
@@ -60,14 +64,27 @@
        void beginFill(const rgba& color);
 
        /// Start drawing with a linear gradient fill
-       void beginLinearGradientFill(const std::vector<gradient_record>& grad, 
const SWFMatrix& mat);
+       void beginLinearGradientFill(const std::vector<gradient_record>& grad,
+            const SWFMatrix& mat);
 
        /// Start drawing with a radial gradient fill
-       void beginRadialGradientFill(const std::vector<gradient_record>& grad, 
const SWFMatrix& mat);
+       void beginRadialGradientFill(const std::vector<gradient_record>& grad,
+            const SWFMatrix& mat);
 
        /// Close an existing filled path, if any.
        void endFill();
 
+    const rect& getBounds() const {
+        return _shape.getBounds();
+    }
+
+    void setBounds(const rect& bounds) {
+        _shape.setBounds(bounds);
+    }
+
+    /// Display a DynamicShape object.
+    void display(const DisplayObject& inst);
+
        /// Set current line style and start a new path.
        //
        /// @param thickness
@@ -122,11 +139,11 @@
        ///
        size_t add_line_style(const line_style& stl);
 
-       // Override from shape_character_def to call ::finalize
+       // Override from DefineShapeTag to call ::finalize
        // NOTE: this is not correct in that a call to hitTest should
        //       not force closing the path being drawn.
-       //       Instead, the closeup should be "temporary" and int
-       //       the point_test_local itself (but only for dynamic drawing).
+       //       Instead, the closeup should be "temporary" and in
+       //       the pointTestLocal itself (but only for dynamic drawing).
        //       We need to add a testcase for this as we currently have none.
        //       The testcase would look like this:
        //
@@ -139,26 +156,31 @@
        //       would result in a triangle and a stroke, which should fail the 
last hitTest(2,8).
        //
        //
-       bool point_test_local(boost::int32_t x, boost::int32_t y,
-            const SWFMatrix& wm)
+       bool pointTestLocal(boost::int32_t x, boost::int32_t y,
+            const SWFMatrix& wm) const
        {
                finalize();
-               return shape_character_def::point_test_local(x, y, wm);
+               return geometry::pointTest(_shape.paths(), _shape.lineStyles(), 
x, y,
+                wm);
        }
 
+    const SWF::ShapeRecord& shapeRecord() const {
+        return _shape;
+    }
+
        /// Add a path, updating _currpath and recomputing bounds
        //
        /// TODO: make private? Only current user is BitmapMovieDefinition.
        ///       It needs this function unless we provide a mean to add a
        ///       Bitmap-Filled path    
        ///
-       void add_path(const path& pth);
+       void add_path(const Path& pth);
 
        /// Always call this function before displaying !
        //
        /// It will take care of cleaning up the drawing
        /// and setting up correct fill styles
-       void finalize();
+       void finalize() const;
 
 private:
 
@@ -170,10 +192,9 @@
        /// for origin, fill and line styles.
        ///
        /// If newShape is true the new shape will start a new subshape.
-       ///
        void startNewPath(bool newShape);
 
-       path* _currpath;
+       Path* _currpath;
 
        size_t _currfill;
 
@@ -185,10 +206,12 @@
        // Current pen Y position
        boost::int32_t  _y;
 
-       // Call this function when the drawing changes !
-       void changed() { _changed = true; }
+       mutable bool _changed;
 
-       bool _changed;
+    /// The actual SWF::ShapeRecord wrapped by this class.
+    //
+    /// Mutable for lazy finalization.
+    mutable SWF::ShapeRecord _shape;
 };
 
 }      // end namespace gnash

=== modified file 'libcore/ExportableResource.h'
--- a/libcore/ExportableResource.h      2009-02-25 22:33:03 +0000
+++ b/libcore/ExportableResource.h      2009-04-07 12:34:43 +0000
@@ -29,7 +29,7 @@
 
 /// A class for SWF resources that may be exported
 //
-/// They are: character_def, sound_sample, and font.
+/// They are: DefinitionTag, sound_sample, and font.
 /// These may be held in the export map of a SWFMovieDefinition.
 class ExportableResource : public ref_counted
 {

=== modified file 'libcore/Font.cpp'
--- a/libcore/Font.cpp  2009-04-03 09:18:40 +0000
+++ b/libcore/Font.cpp  2009-04-07 11:14:10 +0000
@@ -23,11 +23,12 @@
 #include "smart_ptr.h" // GNASH_USE_GC
 #include "Font.h"
 #include "log.h"
-#include "shape_character_def.h"
+#include "ShapeRecord.h"
 #include "DefineFontTag.h"
 #include "FreetypeGlyphsProvider.h"
 
 #include <utility> // for std::make_pair
+#include <memory>
 
 namespace gnash {
 
@@ -54,28 +55,27 @@
 
 Font::GlyphInfo::GlyphInfo()
        :
-       glyph(),
        advance(0)
 {}
 
-Font::GlyphInfo::GlyphInfo(boost::intrusive_ptr<shape_character_def> glyph,
+Font::GlyphInfo::GlyphInfo(std::auto_ptr<SWF::ShapeRecord> glyph,
         float advance)
        :
-       glyph(glyph.get()),
+       glyph(glyph.release()),
        advance(advance)
 {}
 
 Font::GlyphInfo::GlyphInfo(const GlyphInfo& o)
        :
-       glyph(o.glyph.get()),
+       glyph(o.glyph),
        advance(o.advance)
 {}
 
+
 #ifdef GNASH_USE_GC
 void
 Font::GlyphInfo::markReachableResources() const
 {
-       if ( glyph ) glyph->setReachable();
 }
 #endif
 
@@ -109,7 +109,7 @@
 {
 }
 
-shape_character_def*
+SWF::ShapeRecord*
 Font::get_glyph(int index, bool embedded) const
 {
     // What to do if embedded is true and this is a
@@ -296,10 +296,9 @@
     float advance;
 
     // Get the vectorial glyph
-    boost::intrusive_ptr<shape_character_def> sh = 
-        _ftProvider->getGlyph(code, advance);
+    std::auto_ptr<SWF::ShapeRecord> sh = _ftProvider->getGlyph(code, advance);
 
-    if (!sh) {
+    if (!sh.get()) {
         log_error("Could not create shape "
                 "glyph for DisplayObject code %u (%c) with "
                 "device font %s (%p)", code, code, _name,
@@ -371,8 +370,6 @@
 /// Mark reachable resources (for the GC)
 //
 /// Reachable resources are:
-///    - shape_character_defs (vector glyphs, devide and embeded)
-///
 void
 Font::markReachableResources() const
 {

=== modified file 'libcore/Font.h'
--- a/libcore/Font.h    2009-04-03 09:18:40 +0000
+++ b/libcore/Font.h    2009-04-07 12:34:43 +0000
@@ -29,13 +29,14 @@
 #include <boost/scoped_ptr.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/cstdint.hpp>
+#include <memory>
 #include <vector>
 #include <map>
 
 namespace gnash {
-    class shape_character_def;
     class FreetypeGlyphsProvider;
     namespace SWF {
+        class ShapeRecord;
         class DefineFontTag;
     }
 }
@@ -93,7 +94,6 @@
        ///
        /// @param italic
        ///     Whether to use the italic variant of the font.
-       ///
        Font(const std::string& name, bool bold=false, bool italic=false);
 
        ~Font();
@@ -110,7 +110,6 @@
        ///
        /// @param italic
        ///     Italic flag
-       ///
        bool matches(const std::string& name, bool bold, bool italic) const;
 
        void testInvariant()
@@ -120,23 +119,22 @@
        /// Get glyph by index.
        //
        /// @param glyph_index
-       ///     Index of the glyph. See get_glyph_index() to obtain by 
DisplayObject code.
+       ///     Index of the glyph. See get_glyph_index() to obtain by 
character code.
        ///
        /// @param embedded
        ///     If true, queries the 'embedded' glyphs table, 
        ///     otherwise, looks in the 'device' font table.
        ///
        /// @return
-       ///     The glyph outline, or NULL if out of range.
-       ///     (would be a programming error most likely)
-       ///
-       ///
-       shape_character_def* get_glyph(int glyph_index, bool embedded) const;
+       ///     The glyph outline, or NULL if out of range. (would be a
+    /// programming error most likely). The ShapeRecord is owned by
+    /// the Font class.
+    SWF::ShapeRecord* get_glyph(int glyph_index, bool embedded) const;
 
        /// Get name of this font. 
        const std::string& name() const { return _name; }
 
-       /// Return the glyph index for a given DisplayObject code
+       /// Return the glyph index for a given character code
        //
        /// @param code
        ///     Character code to fetch the corresponding glyph index of.
@@ -158,7 +156,7 @@
        /// Return the advance value for the given glyph index
        //
        /// @param glyph_index
-       ///     Index of the glyph. See get_glyph_index() to obtain by 
DisplayObject code.
+       ///     Index of the glyph. See get_glyph_index() to obtain by 
character code.
        ///
        /// @param embedded
        ///     If true, queries the 'embedded' glyphs table, 
@@ -215,18 +213,19 @@
         // no glyph, default textured glyph, 0 advance
         GlyphInfo();
 
-        // given glyph and advance, default textured glyph
-        GlyphInfo(boost::intrusive_ptr<shape_character_def> glyph,
-                float advance);
+        /// Construct default textured glyph
+        //
+        /// Takes ownership of the SWF::ShapeRecord.
+        GlyphInfo(std::auto_ptr<SWF::ShapeRecord> glyph, float advance);
 
-        GlyphInfo(const GlyphInfo&);
+        GlyphInfo(const GlyphInfo& o);
 
 #ifdef GNASH_USE_GC
         /// Mark any glyph and texture glyph resources as reachable
         void markReachableResources() const;
 #endif
 
-        boost::intrusive_ptr<shape_character_def> glyph;
+        boost::shared_ptr<SWF::ShapeRecord> glyph;
 
         float advance;
     };
@@ -322,7 +321,7 @@
        /// Mark reachable resources (for the GC)
        //
        /// Reachable resources are:
-       ///     - shape_character_defs (vector glyphs)
+       ///     - DefineShapeTags (vector glyphs)
        ///
        void markReachableResources() const;
 #endif // GNASH_USE_GC

=== modified file 'libcore/FreetypeGlyphsProvider.cpp'
--- a/libcore/FreetypeGlyphsProvider.cpp        2009-04-03 09:18:40 +0000
+++ b/libcore/FreetypeGlyphsProvider.cpp        2009-04-07 12:23:59 +0000
@@ -25,7 +25,7 @@
 #include "GnashImage.h" // for create_alpha
 #include "GnashException.h"
 #include "render.h"
-#include "DynamicShape.h"
+#include "ShapeRecord.h"
 #include "log.h"
 
 #ifdef USE_FREETYPE 
@@ -70,24 +70,39 @@
 //
 /// See  FT_Outline_Decompose function of freetype2 lib
 ///
-class OutlineWalker {
+class OutlineWalker
+{
 
 public:
 
        /// Create an outline walker drawing to the given DynamiShape
        //
        /// @param sh
-       ///     The DynamiShape to draw to. Externally owned.
+       ///     The DynamicShape to draw to. Externally owned.
        ///
        /// @param scale
        ///     The scale to apply to coordinates.
        ///     This is to match an arbitrary EM 
        ///
-       OutlineWalker(DynamicShape& sh, float scale)
+       OutlineWalker(SWF::ShapeRecord& sh, float scale)
                :
-               _sh(sh),
-               _scale(scale)
-       {}
+               _shape(sh),
+               _scale(scale),
+        _currPath(0),
+        _x(0),
+        _y(0)
+       {
+        fill_style f;
+        f.setSolid(rgba(255, 255, 255, 255));
+        _shape.addFillStyle(f);
+        _shape.addPath(Path(_x, _y, 1, 0, 0, true));
+        _currPath = &_shape.currentPath();
+    }
+
+    void finish() 
+    {
+        _currPath->close();
+    }
 
        ~OutlineWalker() {}
 
@@ -121,26 +136,25 @@
        /// falling in the middle of the two control points.
        ///
        static int
-       walkCubicTo(FT_CONST FT_Vector* ctrl1, FT_CONST FT_Vector* ctrl2, 
FT_CONST FT_Vector* to, void* ptr)
+       walkCubicTo(FT_CONST FT_Vector* ctrl1, FT_CONST FT_Vector* ctrl2,
+            FT_CONST FT_Vector* to, void* ptr)
        {
                OutlineWalker* walker = static_cast<OutlineWalker*>(ptr);
                return walker->cubicTo(ctrl1, ctrl2, to);
        }
 
 private:
-
-       DynamicShape& _sh;
-
-       float _scale;
-
-       int moveTo(const FT_Vector* to)
+       
+    int moveTo(const FT_Vector* to)
        {
 #ifdef DEBUG_OUTLINE_DECOMPOSITION 
                log_debug("moveTo: %ld,%ld", to->x, to->y);
 #endif
-        boost::int32_t  x = static_cast<boost::int32_t>(to->x * _scale);
-        boost::int32_t  y = static_cast<boost::int32_t>(to->y * _scale);
-               _sh.moveTo(x, -y);
+        _x = static_cast<boost::int32_t>(to->x * _scale);
+        _y = - static_cast<boost::int32_t>(to->y * _scale);
+        _currPath->close();
+        _shape.addPath(Path(_x, _y, 1, 0, 0, false));
+        _currPath = &_shape.currentPath();
                return 0;
        }
 
@@ -149,10 +163,10 @@
 #ifdef DEBUG_OUTLINE_DECOMPOSITION 
                log_debug("lineTo: %ld,%ld", to->x, to->y);
 #endif
-               static const int swfVersion = 6; // we have no thickness, so 6 
is fine
-        boost::int32_t  x = static_cast<boost::int32_t>(to->x * _scale);
-        boost::int32_t  y = static_cast<boost::int32_t>(to->y * _scale);
-               _sh.lineTo(x, -y, swfVersion);
+        _x = static_cast<boost::int32_t>(to->x * _scale);
+        _y = - static_cast<boost::int32_t>(to->y * _scale);
+               _currPath->drawLineTo(_x, _y);
+        expandBounds(_x, _y);
                return 0;
        }
 
@@ -161,12 +175,12 @@
 #ifdef DEBUG_OUTLINE_DECOMPOSITION 
                log_debug("conicTo: %ld,%ld %ld,%ld", ctrl->x, ctrl->y, to->x, 
to->y);
 #endif
-        boost::int32_t  x1 = static_cast<boost::int32_t>(ctrl->x * _scale);
-        boost::int32_t  y1 = static_cast<boost::int32_t>(ctrl->y * _scale);
-        boost::int32_t  x2 = static_cast<boost::int32_t>(to->x * _scale);
-        boost::int32_t  y2 = static_cast<boost::int32_t>(to->y * _scale);
-        static const int swfVersion = 6; // we have no thickness, so 6 is fine
-               _sh.curveTo(x1, -y1, x2, -y2, swfVersion);
+        boost::int32_t x1 = static_cast<boost::int32_t>(ctrl->x * _scale);
+        boost::int32_t y1 = static_cast<boost::int32_t>(ctrl->y * _scale);
+        _x = static_cast<boost::int32_t>(to->x * _scale);
+        _y = - static_cast<boost::int32_t>(to->y * _scale);
+               _currPath->drawCurveTo(x1, -y1, _x, _y);
+               expandBounds(x1, -y1, _x, _y);
                return 0;
        }
 
@@ -174,21 +188,47 @@
        cubicTo(const FT_Vector* ctrl1, const FT_Vector* ctrl2, const 
FT_Vector* to)
        {
 #ifdef DEBUG_OUTLINE_DECOMPOSITION 
-               log_debug("cubicTo: %ld,%ld %ld,%ld %ld,%ld", ctrl1->x, 
ctrl1->y, ctrl2->x, ctrl2->y, to->x, to->y);
+               log_debug("cubicTo: %ld,%ld %ld,%ld %ld,%ld", ctrl1->x,
+                ctrl1->y, ctrl2->x, ctrl2->y, to->x, to->y);
 #endif
-
                float x = ctrl1->x + ( (ctrl2->x - ctrl1->x) * 0.5 );
                float y = ctrl1->y + ( (ctrl2->y - ctrl1->y) * 0.5 );
         boost::int32_t x1 = static_cast<boost::int32_t>(x * _scale);
         boost::int32_t y1 = static_cast<boost::int32_t>(y * _scale);
-        boost::int32_t x2 = static_cast<boost::int32_t>(to->x * _scale);
-        boost::int32_t y2 = static_cast<boost::int32_t>(to->y * _scale);
+        _x = static_cast<boost::int32_t>(to->x * _scale);
+        _y = - static_cast<boost::int32_t>(to->y * _scale);
         
-               static const int swfVersion = 6; // we have no thickness, so 6 
is fine
-               _sh.curveTo(x1, -y1, x2, -y2, swfVersion);
-               return 0;
+               _currPath->drawCurveTo(x1, -y1, _x, _y);
+               expandBounds(x1, -y1, _x, _y);
+        return 0;
        }
-
+    
+    void expandBounds(int x, int y) {
+        rect bounds = _shape.getBounds();
+        if (_currPath->size() == 1) _currPath->expandBounds(bounds, 0, 6);
+        else {
+            bounds.expand_to_circle(x, y, 0);
+        }
+        _shape.setBounds(bounds);
+    }
+
+    void expandBounds(int ax, int ay, int cx, int cy) {
+        rect bounds = _shape.getBounds();
+        if (_currPath->size() == 1) _currPath->expandBounds(bounds, 0, 6);
+        else {
+            bounds.expand_to_circle(ax, ay, 0);
+            bounds.expand_to_circle(cx, cy, 0);
+        }
+        _shape.setBounds(bounds);
+    }
+
+    SWF::ShapeRecord& _shape;
+
+       const float _scale;
+
+    Path* _currPath;
+
+    boost::int32_t _x, _y;
 
 };
 
@@ -402,16 +442,18 @@
 #endif // ndef USE_FREETYPE 
 
 #ifdef USE_FREETYPE
-boost::intrusive_ptr<shape_character_def>
+std::auto_ptr<SWF::ShapeRecord>
 FreetypeGlyphsProvider::getGlyph(boost::uint16_t code, float& advance)
 {
-       boost::intrusive_ptr<DynamicShape> sh;
-
-       FT_Error error = FT_Load_Char(m_face, code, 
FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE);
-       if ( error != 0 )
-       {
-               log_error("Error loading freetype outline glyph for char '%c' 
(error: %d)", code, error);
-               return sh.get();
+    std::auto_ptr<SWF::ShapeRecord> glyph;
+
+       FT_Error error = FT_Load_Char(m_face, code, FT_LOAD_NO_BITMAP | 
+                                                FT_LOAD_NO_SCALE);
+
+       if (error) {
+               log_error("Error loading freetype outline glyph for char '%c' "
+                "(error: %d)", code, error);
+               return glyph;
        }
 
        // Scale advance by current scale, to match expected output coordinate 
space
@@ -431,22 +473,13 @@
                        static_cast<char>((gf>>16)&0xff),
                        static_cast<char>((gf>>8)&0xff),
                        static_cast<char>(gf&0xff));
-               return 0;
+               return glyph;
        }
-       //assert(m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE);
 
        FT_Outline* outline = &(m_face->glyph->outline);
 
-       //FT_BBox       glyphBox;
-       //FT_Outline_Get_BBox(outline, &glyphBox);
-       //rect r(glyphBox.xMin, glyphBox.yMin, glyphBox.xMax, glyphBox.yMax);
-       //log_debug("Glyph for DisplayObject '%c' has computed bounds %s", 
code, r.toString().c_str());
-
-       sh = new DynamicShape();
-       sh->beginFill(rgba(255, 255, 255, 255));
-
        FT_Outline_Funcs walk;
-               walk.move_to = OutlineWalker::walkMoveTo;
+    walk.move_to = OutlineWalker::walkMoveTo;
        walk.line_to = OutlineWalker::walkLineTo;
        walk.conic_to = OutlineWalker::walkConicTo;
        walk.cubic_to = OutlineWalker::walkCubicTo;
@@ -456,8 +489,10 @@
 #ifdef DEBUG_OUTLINE_DECOMPOSITION 
        log_debug("Decomposing glyph outline for DisplayObject %u", code);
 #endif
+    
+    glyph.reset(new SWF::ShapeRecord);
 
-       OutlineWalker walker(*sh, scale);
+       OutlineWalker walker(*glyph, scale);
 
        FT_Outline_Decompose(outline, &walk, &walker);
 #ifdef DEBUG_OUTLINE_DECOMPOSITION 
@@ -466,10 +501,13 @@
                        code, bound.toString());
 #endif
 
-       return sh.get();
+    walker.finish();
+
+       return glyph;
 }
 #else // ndef(USE_FREETYPE)
-boost::intrusive_ptr<shape_character_def>
+
+SWF::ShapeRecord*
 FreetypeGlyphsProvider::getGlyph(boost::uint16_t, float& advance)
 {
        abort(); // should never be called... 

=== modified file 'libcore/FreetypeGlyphsProvider.h'
--- a/libcore/FreetypeGlyphsProvider.h  2009-04-03 09:18:40 +0000
+++ b/libcore/FreetypeGlyphsProvider.h  2009-04-07 12:34:43 +0000
@@ -35,7 +35,9 @@
 
 // Forward declarations
 namespace gnash {
-       class shape_character_def;
+    namespace SWF {
+        class ShapeRecord;
+    }
 }
 
 
@@ -50,7 +52,7 @@
 /// but I think the actual size could change between glyphs (see the 'box'
 /// parameter of getRenderedGlyph() method).
 ///
-/// Vectorial glyphs are instances of a shape_character_def, same class
+/// Vectorial glyphs are instances of a DefineShapeTag, same class
 /// resulting from parsing of embedded fonts.
 ///
 class FreetypeGlyphsProvider 
@@ -96,11 +98,12 @@
        ///     Output parameter... units to advance horizontally from this
        ///     glyph to the next, in unitsPerEM() units.
        ///
-       /// @return A shape_character_def in unitsPerEM() coordinates,
+       /// @return A DefineShapeTag in unitsPerEM() coordinates,
        ///         or a NULL pointer if the given DisplayObject code
        ///         doesn't exist in this font.
        ///
-       boost::intrusive_ptr<shape_character_def> getGlyph(boost::uint16_t 
code, float& advance);
+    std::auto_ptr<SWF::ShapeRecord> getGlyph(boost::uint16_t code,
+            float& advance);
 
        /// Return the number of units of glyphs EM
        //

=== added file 'libcore/Geometry.cpp'
--- a/libcore/Geometry.cpp      1970-01-01 00:00:00 +0000
+++ b/libcore/Geometry.cpp      2009-04-07 13:44:07 +0000
@@ -0,0 +1,301 @@
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include <cmath>
+#include "Geometry.h"
+
+namespace gnash {
+namespace geometry {
+
+namespace {
+
+// TODO: this should be moved to libgeometry or something
+// Finds the quadratic bezier curve crossings with the line Y.
+// The function can have zero, one or two solutions (cross1, cross2). The
+// return value of the function is the number of solutions.
+// x0, y0 = start point of the curve
+// x1, y1 = end point of the curve (anchor, aka ax|ay)
+// cx, cy = control point of the curve
+// If there are two crossings, cross1 is the nearest to x0|y0 on the curve.
+int curve_x_crossings(float x0, float y0, float x1, float y1,
+    float cx, float cy, float y, float &cross1, float &cross2)
+{
+    int count=0;
+
+    // check if any crossings possible
+    if ( ((y0 < y) && (y1 < y) && (cy < y))
+        || ((y0 > y) && (y1 > y) && (cy > y)) )
+    {
+        // all above or below -- no possibility of crossing
+        return 0;
+    }
+
+    // Quadratic bezier is:
+    //
+    // p = (1-t)^2 * a0 + 2t(1-t) * c + t^2 * a1
+    //
+    // We need to solve for x at y.
+
+    // Use the quadratic formula.
+
+    // Numerical Recipes suggests this variation:
+    // q = -0.5 [b +sgn(b) sqrt(b^2 - 4ac)]
+    // x1 = q/a;  x2 = c/q;
+
+    float A = y1 + y0 - 2 * cy;
+    float B = 2 * (cy - y0);
+    float C = y0 - y;
+
+    float rad = B * B - 4 * A * C;
+
+    if (rad < 0)
+    {
+        return 0;
+    }
+    else
+    {
+        float q;
+        float sqrt_rad = std::sqrt(rad);
+        if (B < 0)
+        {
+            q = -0.5f * (B - sqrt_rad);
+        }
+        else
+        {
+            q = -0.5f * (B + sqrt_rad);
+        }
+
+        // The old-school way.
+        // float t0 = (-B + sqrt_rad) / (2 * A);
+        // float t1 = (-B - sqrt_rad) / (2 * A);
+
+        if (q != 0)
+        {
+            float t1 = C / q;
+            if (t1 >= 0 && t1 < 1)
+            {
+                float x_at_t1 =
+                    x0 + 2 * (cx - x0) * t1 + (x1 + x0 - 2 * cx) * t1 * t1;
+
+                count++;
+                assert(count==1);
+                cross1 = x_at_t1;             // order is important!
+            }
+        }
+
+        if (A != 0)
+        {
+            float t0 = q / A;
+            if (t0 >= 0 && t0 < 1)
+            {
+                float x_at_t0 =
+                    x0 + 2 * (cx - x0) * t0 + (x1 + x0 - 2 * cx) * t0 * t0;
+
+                count++;
+                // order is important!
+                if (count == 2) cross2 = x_at_t0;
+                else cross1 = x_at_t0;
+            }
+        }
+
+    }
+
+    return count;
+}
+
+} // anonymous namespace
+
+bool
+pointTest(const std::vector<Path>& paths,
+        const std::vector<line_style>& lineStyles, boost::int32_t x,
+        boost::int32_t y, const SWFMatrix& wm)
+{
+
+    /*
+    Principle:
+    For the fill of the shape, we project a ray from the test point to the left
+    side of the shape counting all crossings. When a line or curve segment is
+    crossed we add 1 if the left fill style is set. Regardless of the left fill
+    style we subtract 1 from the counter then the right fill style is set.
+    This is true when the line goes in downward direction. If it goes upward,
+    the fill styles are reversed.
+
+    The final counter value reveals if the point is inside the shape (and
+    depends on filling rule, see below).
+    This method should not depend on subshapes and work for some malformed
+    shapes situations:
+    - wrong fill side (eg. left side set for a clockwise drawen rectangle)
+    - intersecting paths
+    */
+    point pt(x, y);
+
+    // later we will need non-zero for glyphs... (TODO)
+    bool even_odd = true;  
+
+    unsigned npaths = paths.size();
+    int counter = 0;
+
+    // browse all paths
+    for (unsigned pno=0; pno<npaths; pno++)
+    {
+        const Path& pth = paths[pno];
+        unsigned nedges = pth.m_edges.size();
+
+        float next_pen_x = pth.ap.x;
+        float next_pen_y = pth.ap.y;
+        float pen_x, pen_y;
+
+        if (pth.m_new_shape)
+        {
+            if (( even_odd && (counter % 2) != 0) ||
+                 (!even_odd && (counter != 0)) )
+            {
+                // the point is inside the previous subshape, so exit now
+                return true;
+            }
+
+            counter=0;
+        }
+        if (pth.empty()) continue;
+
+        // If the path has a line style, check for strokes there
+        if (pth.m_line != 0 )
+        {
+            assert(lineStyles.size() >= pth.m_line);
+            const line_style& ls = lineStyles[pth.m_line-1];
+            double thickness = ls.getThickness();
+            if (! thickness )
+            {
+                thickness = 20; // at least ONE PIXEL thick.
+            }
+            else if ((!ls.scaleThicknessVertically()) &&
+                    (!ls.scaleThicknessHorizontally()) )
+            {
+                // TODO: pass the SWFMatrix to withinSquareDistance instead ?
+                double xScale = wm.get_x_scale();
+                double yScale = wm.get_y_scale();
+                thickness *= std::max(xScale, yScale);
+            }
+            else if (ls.scaleThicknessVertically() != 
+                    ls.scaleThicknessHorizontally())
+            {
+                LOG_ONCE(log_unimpl("Collision detection for "
+                            "unidirectionally scaled strokes"));
+            }
+
+            double dist = thickness / 2.0;
+            double sqdist = dist * dist;
+            if (pth.withinSquareDistance(pt, sqdist))
+                return true;
+        }
+
+        // browse all edges of the path
+        for (unsigned eno=0; eno<nedges; eno++)
+        {
+            const Edge& edg = pth.m_edges[eno];
+            pen_x = next_pen_x;
+            pen_y = next_pen_y;
+            next_pen_x = edg.ap.x;
+            next_pen_y = edg.ap.y;
+
+            float cross1, cross2;
+            int dir1, dir2 = 0; // +1 = downward, -1 = upward
+            int crosscount = 0;
+
+            if (edg.straight())
+            {
+                // ignore horizontal lines
+                // TODO: better check for small difference?
+                if (edg.ap.y == pen_y)  
+                {
+                    continue;
+                }
+                // does this line cross the Y coordinate?
+                if ( ((pen_y <= y) && (edg.ap.y >= y))
+                    || ((pen_y >= y) && (edg.ap.y <= y)) )
+                {
+
+                    // calculate X crossing
+                    cross1 = pen_x + (edg.ap.x - pen_x) *
+                        (y - pen_y) / (edg.ap.y - pen_y);
+
+                    if (pen_y > edg.ap.y)
+                        dir1 = -1;  // upward
+                    else
+                        dir1 = +1;  // downward
+
+                    crosscount = 1;
+                }
+                else
+                {
+                    // no crossing found
+                    crosscount = 0;
+                }
+            }
+            else
+            {
+                // ==> curve case
+                crosscount = curve_x_crossings(pen_x, pen_y, edg.ap.x, 
edg.ap.y,
+                    edg.cp.x, edg.cp.y, y, cross1, cross2);
+                dir1 = pen_y > y ? -1 : +1;
+                dir2 = dir1 * (-1); // second crossing always in opposite dir.
+            } // curve
+
+            // ==> we have now:
+            //  - one (cross1) or two (cross1, cross2) ray crossings (X
+            //    coordinate)
+            //  - dir1/dir2 tells the direction of the crossing
+            //    (+1 = downward, -1 = upward)
+            //  - crosscount tells the number of crossings
+
+            // need at least one crossing
+            if (crosscount == 0)
+            {
+                continue;
+            }
+
+            bool touched = false;
+
+            // check first crossing
+            if (cross1 <= x)
+            {
+                if (pth.m_fill0 > 0) counter += dir1;
+                if (pth.m_fill1 > 0) counter -= dir1;
+
+                touched = true;
+            }
+
+            // check optional second crossing (only possible with curves)
+            if ( (crosscount > 1) && (cross2 <= x) )
+            {
+                if (pth.m_fill0 > 0) counter += dir2;
+                if (pth.m_fill1 > 0) counter -= dir2;
+
+                touched = true;
+            }
+
+        }// for edge
+    } // for path
+
+    return ( (even_odd && (counter % 2) != 0) ||
+             (!even_odd && (counter != 0)) );
+}
+
+} // namespace geometry
+} // namespace gnash
+
+

=== modified file 'libcore/Geometry.h'
--- a/libcore/Geometry.h        2009-03-10 20:43:50 +0000
+++ b/libcore/Geometry.h        2009-04-07 12:34:43 +0000
@@ -15,12 +15,13 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-
 #ifndef GNASH_GEOMETRY_H
 #define GNASH_GEOMETRY_H
 
 #include "dsodefs.h"
 #include "SWFMatrix.h" 
+#include "styles.h"
+#include "log.h"
 
 #include <vector> // for path composition
 #include <cmath> // sqrt
@@ -28,54 +29,56 @@
 
 // Forward declarations
 namespace gnash {
-  class rect; 
+    class rect; 
 }
 
 namespace gnash { 
 
-  /// \brief
-  /// Defines an edge with a control point and an anchor point.
-  /// 
-  /// Could be a quadratic bezier curve, or a straight line(degenerated curve).
-  ///
-  class Edge
-  {
-  public:
-       
+/// \brief
+/// Defines an edge with a control point and an anchor point.
+/// 
+/// Could be a quadratic bezier curve, or a straight line(degenerated curve).
+///
+class Edge
+{
+public:
+    
     // Quadratic bezier: point = p0 * t^2 + p1 * 2t(1-t) + p2 * (1-t)^2
     point cp; // control point, TWIPS
-    point ap; // anchor  point, TWIPS
+    point ap; // anchor    point, TWIPS
 
     Edge() 
         :
-    cp(0, 0), ap(0, 0)
-    {  };
+        cp(0, 0),
+        ap(0, 0)
+    {}
     
-    Edge(boost::int32_t cx, boost::int32_t cy, boost::int32_t ax, 
boost::int32_t ay)
-      :
-      cp(cx, cy), ap(ax, ay)
-    {  }
+    Edge(boost::int32_t cx, boost::int32_t cy, boost::int32_t ax,
+            boost::int32_t ay)
+        :
+        cp(cx, cy),
+        ap(ax, ay)
+    {}
 
     Edge(const Edge& from)
-      : 
-      cp(from.cp), ap(from.ap)
-    {  }
+        : 
+        cp(from.cp),
+        ap(from.ap)
+    {}
 
     Edge(const point& ncp, const point& nap)
-      :
-      cp(ncp), ap(nap)
-    {  }
+        :
+        cp(ncp),
+        ap(nap)
+    {}
 
-    bool isStraight() const
+    bool straight() const
     {
         return cp == ap;
     }
-
-    // TODO: drop this!
-    bool is_straight() const { return isStraight(); }
     
     /// Transform the edge according to the given SWFMatrix.
-    void  transform(const SWFMatrix& mat)
+    void transform(const SWFMatrix& mat)
     {
         mat.transform(ap);
         mat.transform(cp);
@@ -96,7 +99,8 @@
         boost::int32_t pdx = p.x - A.x;
         boost::int32_t pdy = p.y - A.y;
 
-        double u = ( (double)(pdx) * dx + (double)(pdy) * dy ) / ( 
(double)(dx)*dx + (double)(dy)*dy );
+        double u = ( (double)(pdx) * dx + (double)(pdy) * dy ) /
+            ( (double)(dx)*dx + (double)(dy)*dy );
 
         if (u <= 0)
         {
@@ -130,9 +134,7 @@
     ///
 
     static point
-    pointOnCurve(const point& A, 
-        const point& C, 
-        const point& B, float t)
+    pointOnCurve(const point& A, const point& C, const point& B, float t)
     {
         point Q1(A, C, t);
         point Q2(C, B, t);
@@ -151,20 +153,19 @@
     /// @param t the step factor between 0 and 1
     ///
     static boost::int64_t squareDistancePtCurve(const point& A,
-               const point& C,
-               const point& B,
-               const point& p, float t)
+                         const point& C,
+                         const point& B,
+                         const point& p, float t)
     {
-      return p.squareDistance( pointOnCurve(A, C, B, t) );
+        return p.squareDistance( pointOnCurve(A, C, B, t) );
     }
-  };
-
-
-  ///\brief
-  /// A subset of a shape, a series of edges sharing a single set of styles. 
-  class DSOEXPORT Path
-  {
-  public:
+};
+
+
+/// A subset of a shape, a series of edges sharing a single set of styles. 
+class DSOEXPORT Path
+{
+public:
     /// Left fill style index (1-based)
     unsigned m_fill0;
 
@@ -189,53 +190,53 @@
     /// Default constructor
     //
     /// @param newShape
-    ///  True if this path starts a new subshape
+    ///    True if this path starts a new subshape
     ///
     Path(bool newShape = false)
-      : 
-    m_new_shape(newShape)
+        : 
+        m_new_shape(newShape)
     {
-      reset(0, 0, 0, 0, 0);
+        reset(0, 0, 0, 0, 0);
     }
 
     Path(const Path& from)
-      : 
-      m_fill0(from.m_fill0),
-      m_fill1(from.m_fill1),
-      m_line(from.m_line),
-      ap(from.ap),
-      m_edges(from.m_edges),
-      m_new_shape(from.m_new_shape)        
+        : 
+        m_fill0(from.m_fill0),
+        m_fill1(from.m_fill1),
+        m_line(from.m_line),
+        ap(from.ap),
+        m_edges(from.m_edges),
+        m_new_shape(from.m_new_shape)                
     {
     }
     
     /// Initialize a path 
     //
     /// @param ax
-    ///  X coordinate of path origin in TWIPS
+    ///    X coordinate of path origin in TWIPS
     ///
     /// @param ay
-    ///  Y coordinate in path origin in TWIPS
+    ///    Y coordinate in path origin in TWIPS
     ///
     /// @param fill0
-    ///  Fill style index for left fill (1-based).
-    ///  Zero means NO style.
+    ///    Fill style index for left fill (1-based).
+    ///    Zero means NO style.
     ///
     /// @param fill1
-    ///  Fill style index for right fill (1-based)
-    ///  Zero means NO style.
+    ///    Fill style index for right fill (1-based)
+    ///    Zero means NO style.
     ///
     /// @param line
-    ///  Line style index for right fill (1-based).
-    ///  Zero means NO style.
+    ///    Line style index for right fill (1-based).
+    ///    Zero means NO style.
     ///
     /// @param newShape
-    ///  True if this path starts a new subshape
+    ///    True if this path starts a new subshape
     Path(boost::int32_t ax, boost::int32_t ay, 
-        unsigned fill0, unsigned fill1, unsigned line, 
-        bool newShape)
-      :
-      m_new_shape(newShape)
+            unsigned fill0, unsigned fill1, unsigned line, 
+            bool newShape)
+        :
+        m_new_shape(newShape)
     {
         reset(ax, ay, fill0, fill1, line);
     }
@@ -243,22 +244,22 @@
     /// Re-initialize a path, maintaining the "new shape" flag untouched
     //
     /// @param ax
-    ///  X coordinate of path origin in TWIPS
+    ///    X coordinate of path origin in TWIPS
     ///
     /// @param ay
-    ///  Y coordinate in path origin in TWIPS
+    ///    Y coordinate in path origin in TWIPS
     ///
     /// @param fill0
-    ///  Fill style index for left fill
+    ///    Fill style index for left fill
     ///
     /// @param fill1
-    ///  Fill style index for right fill
+    ///    Fill style index for right fill
     //
     /// @param line
-    ///  Line style index for right fill
+    ///    Line style index for right fill
     ///
-    void  reset(boost::int32_t ax, boost::int32_t ay, 
-        unsigned fill0, unsigned fill1, unsigned line)
+    void reset(boost::int32_t ax, boost::int32_t ay, 
+            unsigned fill0, unsigned fill1, unsigned line)
     // Reset all our members to the given values, and clear our edge list.
     {
         ap.x = ax;
@@ -268,32 +269,26 @@
         m_line = line;
 
         m_edges.resize(0);
-        assert(is_empty());
-    }
-
-    /// Return true if we have no edges.
-    bool  is_empty() const
-    {
-        return m_edges.empty();
+        assert(empty());
     }
 
     /// Expand given rect to include bounds of this path
     //
     /// @param r
-    ///  The rectangle to expand with our own bounds
+    ///    The rectangle to expand with our own bounds
     ///
     /// @param thickness
-    ///  The thickess of our lines, half the thickness will
-    ///  be added in all directions in swf8+, all of it will
-    ///  in swf7-
+    ///    The thickess of our lines, half the thickness will
+    ///    be added in all directions in swf8+, all of it will
+    ///    in swf7-
     ///
     /// @param swfVersion
-    ///  SWF version to use.
+    ///    SWF version to use.
     ///
     void
     expandBounds(rect& r, unsigned int thickness, int swfVersion) const
     {
-        const Path&  p = *this;
+        const Path&    p = *this;
         size_t nedges = m_edges.size();
         
         if ( ! nedges ) return; // this path adds nothing
@@ -302,7 +297,7 @@
         {
             // NOTE: Half of thickness would be enough (and correct) for
             // radius, but that would not match how Flash calculates the
-            // bounds using the drawing API.                        
+            // bounds using the drawing API.                                   
             
             unsigned int radius = swfVersion < 8 ? thickness : thickness/2;
 
             r.expand_to_circle(ap.x, ap.y, radius);
@@ -334,10 +329,10 @@
     /// and expressed in TWIPS.
     ///
     /// @param x
-    ///  X coordinate in TWIPS
+    ///    X coordinate in TWIPS
     ///
     /// @param y
-    ///  Y coordinate in TWIPS
+    ///    Y coordinate in TWIPS
     ///
     void 
     drawLineTo(boost::int32_t dx, boost::int32_t dy)
@@ -351,16 +346,16 @@
     /// expressed in TWIPS.
     ///
     /// @param cx
-    ///  Control point's X coordinate.
+    ///    Control point's X coordinate.
     ///
     /// @param cy
-    ///  Control point's Y coordinate.
+    ///    Control point's Y coordinate.
     ///
     /// @param ax
-    ///  Anchor point's X ordinate.
+    ///    Anchor point's X ordinate.
     ///
     /// @param ay
-    ///  Anchor point's Y ordinate.
+    ///    Anchor point's Y ordinate.
     ///
     void 
     drawCurveTo(boost::int32_t cdx, boost::int32_t cdy, boost::int32_t adx, 
boost::int32_t ady)
@@ -379,20 +374,14 @@
 
 
     /// Returns true if the last and the first point of the path match
-    bool  isClosed() const 
+    bool isClosed() const 
     {
-        if ( m_edges.empty() ) 
-        {
-            return true;  
-        }
-        else
-        {
-            return m_edges.back().ap == ap; 
-        }
+        if (m_edges.empty()) return true;
+        return m_edges.back().ap == ap; 
     }
 
     /// Close this path with a straight line, if not already closed
-    void  close()
+    void close()
     {
         if ( m_edges.empty() ) return;
 
@@ -414,94 +403,93 @@
     bool
     withinSquareDistance(const point& p, double dist) const
     {
-      size_t nedges = m_edges.size();
-
-      if ( ! nedges ) return false;
-
-      point px(ap);
-      for (size_t i=0; i<nedges; ++i)
-      {
-        const Edge& e = m_edges[i];
-        point np(e.ap);
-
-        if ( e.isStraight() )
-        {
-          double d = Edge::squareDistancePtSeg(p, px, np);
-
-          if ( d <= dist ) return true;
-        }
-        else
-        {
-
-          const point& A = px;
-          const point& C = e.cp;
-          const point& B = e.ap;
-
-          // Approximate the curve to segCount segments
-          // and compute distance of query point from each
-          // segment.
-          //
-          // TODO: find an apprpriate value for segCount based
-          //       on rendering scale ?
-          //
-          int segCount = 10; 
-          point p0(A.x, A.y);
-          for (int i=1; i<=segCount; ++i)
-          {
-            float t1 = (float)(i) / segCount;
-            point p1 = Edge::pointOnCurve(A, C, B, t1);
-
-            // distance from point and segment being an approximation 
-            // of the curve 
-            double d = Edge::squareDistancePtSeg(p, p0, p1);
-            if ( d <= dist ) return true;
-
-            p0.setTo(p1.x, p1.y);
-          }
-        }
-        px = np;
-      }
-
-      return false;
+        size_t nedges = m_edges.size();
+
+        if ( ! nedges ) return false;
+
+        point px(ap);
+        for (size_t i=0; i<nedges; ++i)
+        {
+            const Edge& e = m_edges[i];
+            point np(e.ap);
+
+            if (e.straight())
+            {
+                double d = Edge::squareDistancePtSeg(p, px, np);
+                if ( d <= dist ) return true;
+            }
+            else
+            {
+
+                const point& A = px;
+                const point& C = e.cp;
+                const point& B = e.ap;
+
+                // Approximate the curve to segCount segments
+                // and compute distance of query point from each
+                // segment.
+                //
+                // TODO: find an apprpriate value for segCount based
+                //             on rendering scale ?
+                //
+                int segCount = 10; 
+                point p0(A.x, A.y);
+                for (int i=1; i<=segCount; ++i)
+                {
+                    float t1 = (float)(i) / segCount;
+                    point p1 = Edge::pointOnCurve(A, C, B, t1);
+
+                    // distance from point and segment being an approximation 
+                    // of the curve 
+                    double d = Edge::squareDistancePtSeg(p, p0, p1);
+                    if ( d <= dist ) return true;
+
+                    p0.setTo(p1.x, p1.y);
+                }
+            }
+            px = np;
+        }
+
+        return false;
     }
 
     /// Transform all path coordinates according to the given SWFMatrix.
-    void  transform(const SWFMatrix& mat)
+    void transform(const SWFMatrix& mat)
     {
-               mat.transform(ap);
-               std::vector<Edge>::iterator it = m_edges.begin(), ie = 
m_edges.end();
-               for(; it != ie; it++)
-               {
-                       (*it).transform(mat);
-               }
-    }    
+        mat.transform(ap);
+        std::vector<Edge>::iterator it = m_edges.begin(), ie = m_edges.end();
+        for(; it != ie; it++)
+        {
+            (*it).transform(mat);
+        }
+    }        
 
     /// Set this path as the start of a new (sub)shape
-    void  setNewShape() 
+    void setNewShape() 
     { 
-        m_new_shape=true; 
+            m_new_shape=true; 
     }
 
     /// Return true if this path starts a new (sub)shape
-    bool  getNewShape() const 
+    bool getNewShape() const 
     { 
         return m_new_shape; 
     }
 
     /// Return true if this path contains no edges
-    bool  empty() const
+    bool empty() const
     {
-        return is_empty();
+        return m_edges.empty();
     }
 
     /// Set the fill to use on the left side
     //
     /// @param f
-    ///  The fill index (1-based).
-    ///  When this path is added to a shape_character_def,
-    ///  the index (decremented by 1) will reference an element
-    ///  in the fill_style vector defined for that shape.
-    ///  If zero, no fill will be active.
+    ///    The fill index (1-based).
+    ///    When this path is added to a DefineShapeTag,
+    ///    the index (decremented by 1) will reference an element
+    ///    in the fill_style vector defined for that shape.
+    ///    If zero, no fill will be active.
     ///
     void setLeftFill(unsigned f)
     {
@@ -516,11 +504,11 @@
     /// Set the fill to use on the left side
     //
     /// @param f
-    ///  The fill index (1-based).
-    ///  When this path is added to a shape_character_def,
-    ///  the index (decremented by 1) will reference an element
-    ///  in the fill_style vector defined for that shape.
-    ///  If zero, no fill will be active.
+    ///    The fill index (1-based).
+    ///    When this path is added to a DefineShapeTag,
+    ///    the index (decremented by 1) will reference an element
+    ///    in the fill_style vector defined for that shape.
+    ///    If zero, no fill will be active.
     ///
     void setRightFill(unsigned f)
     {
@@ -535,11 +523,11 @@
     /// Set the line style to use for this path
     //
     /// @param f
-    ///  The line_style index (1-based).
-    ///  When this path is added to a shape_character_def,
-    ///  the index (decremented by 1) will reference an element
-    ///  in the line_style vector defined for that shape.
-    ///  If zero, no fill will be active.
+    ///    The line_style index (1-based).
+    ///    When this path is added to a DefineShapeTag,
+    ///    the index (decremented by 1) will reference an element
+    ///    in the line_style vector defined for that shape.
+    ///    If zero, no fill will be active.
     ///
     void setLineStyle(unsigned i)
     {
@@ -574,16 +562,22 @@
     {
         return m_new_shape;
     }
- 
-  }; // end of class Path
-
-
-  typedef Edge  edge;
-  typedef Path  path;
-
-}  // end namespace gnash
-
-#endif // GNASH_SHAPE_H
+
+}; // end of class Path
+
+namespace geometry
+{
+
+bool pointTest(const std::vector<Path>& paths,
+    const std::vector<line_style>& lineStyles, boost::int32_t x,
+    boost::int32_t y, const SWFMatrix& wm);
+
+} // namespace geometry
+
+
+} // namespace gnash
+
+#endif // GNASH_GEOMETRY_H
 
 
 // Local Variables:

=== modified file 'libcore/InteractiveObject.h'
--- a/libcore/InteractiveObject.h       2009-04-04 15:35:18 +0000
+++ b/libcore/InteractiveObject.h       2009-04-07 13:13:16 +0000
@@ -20,12 +20,10 @@
 
 #include "smart_ptr.h" // GNASH_USE_GC
 #include "DisplayObject.h" // for inheritance
-#include "character_def.h"
 
 #include <cassert>
 
 namespace gnash {
-    class character_def;
     class StaticText;
     namespace SWF {
         class TextRecord;

=== modified file 'libcore/Makefile.am'
--- a/libcore/Makefile.am       2009-04-04 15:35:18 +0000
+++ b/libcore/Makefile.am       2009-04-07 12:45:25 +0000
@@ -61,9 +61,11 @@
        DisplayObject.cpp \
        CharacterProxy.cpp \
        cxform.cpp \
+       Geometry.cpp \
        DynamicShape.cpp        \
        Bitmap.cpp \
        Shape.cpp \
+       MorphShape.cpp \
        StaticText.cpp \
        TextField.cpp \
         BlurFilter.cpp \
@@ -91,11 +93,14 @@
        swf/DefineButtonTag.cpp \
        swf/DefineFontTag.cpp \
        swf/VideoFrameTag.cpp \
+       swf/ShapeRecord.cpp \
        swf/SoundInfoRecord.cpp \
        swf/TextRecord.cpp \
        swf/tag_loaders.cpp \
        swf/DefineFontAlignZonesTag.cpp \
+       swf/DefineShapeTag.cpp \
        swf/DefineEditTextTag.cpp \
+       swf/DefineMorphShapeTag.cpp \
        swf/CSMTextSettingsTag.cpp \
        swf/PlaceObject2Tag.cpp \
        swf/RemoveObjectTag.cpp \
@@ -122,7 +127,6 @@
 noinst_HEADERS = \
        Property.h \
        PropertyList.h \
-       Sprite.h \
        StreamProvider.h \
        StringPredicates.h \
        URLAccessManager.h \
@@ -164,6 +168,7 @@
        Font.h \
        fontlib.h \
        Shape.h \
+       MorphShape.h \
        StaticText.h \
        InteractiveObject.h \
        gnash.h \
@@ -190,6 +195,10 @@
        swf/ControlTag.h \
        swf/DefineFontAlignZonesTag.h \
        swf/CSMTextSettingsTag.h \
+       swf/DefineShapeTag.h \
+       swf/DefinitionTag.h \
+       swf/DefineMorphShapeTag.h \
+       swf/ShapeRecord.h \
        swf/SoundInfoRecord.h \
        swf/TextRecord.h \
        swf/DefineButtonSoundTag.h \

=== added file 'libcore/MorphShape.cpp'
--- a/libcore/MorphShape.cpp    1970-01-01 00:00:00 +0000
+++ b/libcore/MorphShape.cpp    2009-04-07 14:32:06 +0000
@@ -0,0 +1,99 @@
+// MorphShape.cpp:  MorphShape handling for Gnash.
+// 
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "MorphShape.h"
+#include "VM.h"
+#include "fill_style.h"
+#include "swf/ShapeRecord.h"
+#include "Geometry.h"
+#include "SWFMatrix.h"
+
+namespace gnash
+{
+
+
+MorphShape::MorphShape(const SWF::DefineMorphShapeTag* const def,
+        DisplayObject* parent, int id)
+    :
+    DisplayObject(parent, id),
+    _def(def),
+    _shape(_def->shape1())
+{
+}
+
+bool
+MorphShape::pointInShape(boost::int32_t x, boost::int32_t y) const
+{
+    SWFMatrix wm = getWorldMatrix();
+    SWFMatrix wm_inverse = wm.invert();
+    point lp(x, y);
+    wm_inverse.transform(lp);
+    
+    // FIXME: if the shape contains non-scaled strokes
+    //        we can't rely on boundary itself for a quick
+    //        way out. Bounds supposedly already include
+    //        thickness, so we might keep a flag telling us
+    //        whether *non_scaled* strokes are present
+    //        and if not still use the boundary check.
+    // NOTE: just skipping this test breaks a corner-case
+    //       in DrawingApiTest (kind of a fill-leakage making
+    //       the collision detection find you inside a self-crossing
+    //       shape).
+    if (!_shape.getBounds().point_test(lp.x, lp.y)) return false;
+
+    return geometry::pointTest(_shape.paths(), _shape.lineStyles(),
+            lp.x, lp.y, wm);
+}
+
+void  
+MorphShape::display()
+{
+    morph();
+    _def->display(*this); 
+    clear_invalidated();
+}
+
+inline double
+MorphShape::currentRatio() const
+{
+    return get_ratio() / 65535.0;
+}
+
+rect
+MorphShape::getBounds() const
+{
+    // TODO: optimize this more.
+    rect bounds = _shape.getBounds();
+    bounds.expand_to_rect(_def->shape2().getBounds());
+    return bounds;
+}
+
+void
+MorphShape::morph()
+{
+    _shape.setLerp(_def->shape1(), _def->shape2(), currentRatio());
+}
+
+
+} // namespace gnash
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

=== added file 'libcore/MorphShape.h'
--- a/libcore/MorphShape.h      1970-01-01 00:00:00 +0000
+++ b/libcore/MorphShape.h      2009-04-07 14:32:06 +0000
@@ -0,0 +1,87 @@
+// MorphShape.h: the MorphShape DisplayObject implementation for Gnash.
+// 
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef GNASH_MORPH_SHAPE_H
+#define GNASH_MORPH_SHAPE_H
+
+#include "smart_ptr.h" // GNASH_USE_GC
+#include "DisplayObject.h"
+#include "Geometry.h"
+#include "swf/DefineMorphShapeTag.h"
+#include <cassert>
+
+namespace gnash {
+
+/// A DisplayObject that tweens between two shapes.
+//
+/// A MorphShape has no properties of its own, but its inherited properties
+/// may be read in AS3 using a reference to the object created with
+/// getChildAt().
+class MorphShape : public DisplayObject
+{
+
+public:
+
+    MorphShape(const SWF::DefineMorphShapeTag* const def, 
+            DisplayObject* parent, int id);
+
+       virtual void display();
+
+    virtual rect getBounds() const;
+    
+    virtual bool pointInShape(boost::int32_t  x, boost::int32_t  y) const;
+ 
+    const SWF::ShapeRecord& shape() const {
+        return _shape;
+    }
+
+protected:
+
+#ifdef GNASH_USE_GC
+       /// Mark reachable resources (for the GC)
+       void markReachableResources() const
+       {
+               assert(isReachable());
+        _def->setReachable();
+               markDisplayObjectReachable();
+       }
+#endif
+
+private:
+    
+    void morph();
+
+    double currentRatio() const;
+
+    const boost::intrusive_ptr<const SWF::DefineMorphShapeTag> _def;
+       
+    SWF::ShapeRecord _shape;
+
+};
+
+
+} // namespace gnash
+
+
+#endif 
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

=== modified file 'libcore/MouseButtonState.h'
--- a/libcore/MouseButtonState.h        2009-04-04 15:35:18 +0000
+++ b/libcore/MouseButtonState.h        2009-04-07 13:13:16 +0000
@@ -8,8 +8,6 @@
 #define GNASH_MOUSE_BUTTON_STATE_H
 
 #include "smart_ptr.h" // GNASH_USE_GC
-#include "character_def.h"
-#include "smart_ptr.h" // for composition and inlines
 #include "InteractiveObject.h" // for use in intrusive_ptr
 
 // Forward declarations

=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp     2009-04-05 07:43:04 +0000
+++ b/libcore/MovieClip.cpp     2009-04-07 12:56:44 +0000
@@ -60,6 +60,7 @@
 #include "flash/geom/Matrix_as.h"
 #include "ExportableResource.h"
 #include "GnashNumeric.h"
+#include "Shape.h"
 
 #ifdef USE_SWFTREE
 # include "tree.hh"
@@ -484,7 +485,7 @@
     InteractiveObject(parent, id),
     m_root(r),
     _drawable(new DynamicShape()),
-    _drawable_inst(_drawable->createDisplayObject(this, 0)),
+    _drawable_inst(new Shape(_drawable, this, 0)),
     m_play_state(PLAY),
     m_current_frame(0),
     m_has_looped(false),
@@ -828,7 +829,7 @@
     newmovieclip->set_event_handlers(get_event_handlers());
 
     // Copy drawable
-    newmovieclip->_drawable = new DynamicShape(*_drawable);
+    newmovieclip->_drawable.reset(new DynamicShape(*_drawable));
     
     newmovieclip->set_cxform(get_cxform());    
     newmovieclip->copyMatrix(*this); // copy SWFMatrix and caches
@@ -1163,6 +1164,7 @@
                         TAG_DLIST|TAG_ACTION);
             }
         }
+
     }
 #ifdef GNASH_DEBUG
     else
@@ -1512,7 +1514,7 @@
     assert(m_def);
     assert(tag);
 
-    character_def* cdef = m_def->get_character_def(tag->getID());
+    SWF::DefinitionTag* cdef = m_def->getDefinitionTag(tag->getID());
     if (!cdef)
     {
         IF_VERBOSE_MALFORMED_SWF(
@@ -1577,7 +1579,7 @@
     assert(m_def != NULL);
     assert(tag != NULL);
 
-    character_def*    cdef = m_def->get_character_def(tag->getID());
+    SWF::DefinitionTag* cdef = m_def->getDefinitionTag(tag->getID());
     if (cdef == NULL)
     {
         log_error(_("movieclip::replace_display_object(): "
@@ -1973,9 +1975,9 @@
 }
 
 DisplayObject*
-MovieClip::getDisplayObject(int /* DisplayObject_id */)
+MovieClip::getDisplayObject(int /* id */)
 {
-    //return m_def->get_character_def(DisplayObject_id);
+    //return m_def->getDefinitionTag(id);
     // @@ TODO -- look through our dlist for a match
     log_unimpl(_("%s doesn't even check for a char"),
         __PRETTY_FUNCTION__);
@@ -2560,7 +2562,7 @@
     rect bounds;
     BoundsFinder f(bounds);
     const_cast<DisplayList&>(m_display_list).visitAll(f);
-    rect drawableBounds = _drawable->get_bound();
+    rect drawableBounds = _drawable->getBounds();
     bounds.expand_to_rect(drawableBounds);
     
     return bounds;
@@ -2645,8 +2647,6 @@
 
     m_display_list.visitAll(marker);
 
-    _drawable->setReachable();
-
     _drawable_inst->setReachable();
 
     m_as_environment.markReachableResources();
@@ -2813,13 +2813,15 @@
 
 #ifdef USE_SWFTREE
 
-class MovieInfoVisitor {
+class MovieInfoVisitor
+{
 
     DisplayObject::InfoTree& _tr;
     DisplayObject::InfoTree::iterator _it;
 
 public:
-    MovieInfoVisitor(DisplayObject::InfoTree& tr, 
DisplayObject::InfoTree::iterator it)
+    MovieInfoVisitor(DisplayObject::InfoTree& tr,
+            DisplayObject::InfoTree::iterator it)
         :
         _tr(tr),
         _it(it)
@@ -3155,8 +3157,8 @@
         return as_value(); 
     }
     
-    character_def* exported_movie =
-        dynamic_cast<character_def*>(exported.get());
+    SWF::DefinitionTag* exported_movie =
+        dynamic_cast<SWF::DefinitionTag*>(exported.get());
 
     if (!exported_movie)
     {

=== modified file 'libcore/MovieClip.h'
--- a/libcore/MovieClip.h       2009-04-05 07:47:59 +0000
+++ b/libcore/MovieClip.h       2009-04-07 12:34:43 +0000
@@ -896,18 +896,10 @@
 
     /// The canvas for dynamic drawing
     //
-    /// WARNING: since DynamicShape is a character_def, which is
-    ///          in turn a ref_counted, we'd better keep
-    ///          this by intrusive_ptr, even if we're the sole
-    ///          owners. The problem is in case a pointer to this
-    ///      instance ever gets passed to some function wrapping
-    ///      it into an intrusive_ptr, in which case the stack
-    ///          object will be destroyed, with horrible consequences ...
-    ///
-    boost::intrusive_ptr<DynamicShape> _drawable;
+    boost::shared_ptr<DynamicShape> _drawable;
 
     /// The need of an instance here is due to the renderer
-    /// insising on availability a shape_character_def instance
+    /// insising on availability a DefineShapeTag instance
     /// that has a parent (why?)
     ///
     boost::intrusive_ptr<DisplayObject> _drawable_inst;

=== modified file 'libcore/Shape.cpp'
--- a/libcore/Shape.cpp 2009-04-03 11:03:31 +0000
+++ b/libcore/Shape.cpp 2009-04-07 13:42:26 +0000
@@ -1,4 +1,4 @@
-// Shape.cpp:  Mouse/Character handling, for Gnash.
+// Shape.cpp: Shape DisplayObject implementation for Gnash.
 // 
 //   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 // 
@@ -29,13 +29,33 @@
     SWFMatrix wm_inverse = wm.invert();
     point lp(x, y);
     wm_inverse.transform(lp);
-    return _def->point_test_local(lp.x, lp.y, wm);
+    
+    // FIXME: if the shape contains non-scaled strokes
+    //        we can't rely on boundary itself for a quick
+    //        way out. Bounds supposedly already include
+    //        thickness, so we might keep a flag telling us
+    //        whether *non_scaled* strokes are present
+    //        and if not still use the boundary check.
+    // NOTE: just skipping this test breaks a corner-case
+    //       in DrawingApiTest (kind of a fill-leakage making
+    //       the collision detection find you inside a self-crossing
+    //       shape).
+    if (_def) {
+        if (!_def->get_bound().point_test(lp.x, lp.y)) return false;
+        return _def->pointTestLocal(lp.x, lp.y, wm);
+    }
+    assert(_shape.get());
+    
+    if (!_shape->getBounds().point_test(lp.x, lp.y)) return false;
+    return _shape->pointTestLocal(lp.x, lp.y, wm);
+
 }
 
 void  
 Shape::display()
 {
-    _def->display(this); // pass in transform info
+    if (_def) _def->display(*this);
+    else _shape->display(*this);
     clear_invalidated();
 }
 

=== modified file 'libcore/Shape.h'
--- a/libcore/Shape.h   2009-04-03 11:03:31 +0000
+++ b/libcore/Shape.h   2009-04-07 12:45:25 +0000
@@ -1,3 +1,4 @@
+// Shape.h: Shape DisplayObject implementation for Gnash.
 // 
 //   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 // 
@@ -20,23 +21,38 @@
 
 #include "smart_ptr.h" // GNASH_USE_GC
 #include "DisplayObject.h"
-#include "shape_character_def.h"
+#include "DefineShapeTag.h"
+#include "DynamicShape.h"
+
 #include <cassert>
+#include <boost/shared_ptr.hpp>
 
 // Forward declarations
 namespace gnash {
-    class character_def;
+    class DefinitionTag;
 }
 
 namespace gnash {
 
 /// For DisplayObjects that don't store unusual state in their instances.
+//
+/// A Shape may be either statically constructed during parsing or,
+/// in AS3, dynamically constructed. A SWF-parsed Shape has an immutable
+/// SWF::DefinitionTag. A dynamic Shape object has a DynamicShape.
 class Shape : public DisplayObject
 {
 
 public:
 
-       Shape(shape_character_def* def, DisplayObject* parent, int id)
+    Shape(boost::shared_ptr<DynamicShape> sh, DisplayObject* parent, int id)
+        :
+        DisplayObject(parent, id),
+        _shape(sh)
+    {
+        assert(_shape.get());
+    }
+
+       Shape(const SWF::DefineShapeTag* const def, DisplayObject* parent, int 
id)
                :
                DisplayObject(parent, id),
                _def(def)
@@ -47,7 +63,7 @@
        virtual void display();
 
     virtual rect getBounds() const {
-        return _def->get_bound();
+        return _def ? _def->get_bound() : _shape->getBounds();
     }
     
     virtual bool pointInShape(boost::int32_t  x, boost::int32_t  y) const;
@@ -59,14 +75,16 @@
        void markReachableResources() const
        {
                assert(isReachable());
-        _def->setReachable();
+        if (_def) _def->setReachable();
                markDisplayObjectReachable();
        }
 #endif
 
 private:
        
-    const boost::intrusive_ptr<shape_character_def> _def;
+    const boost::intrusive_ptr<const SWF::DefineShapeTag> _def;
+
+    boost::shared_ptr<DynamicShape> _shape;
 
 };
 

=== removed file 'libcore/Sprite.h'
--- a/libcore/Sprite.h  2009-04-03 09:18:40 +0000
+++ b/libcore/Sprite.h  1970-01-01 00:00:00 +0000
@@ -1,41 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-//------------------------------------------------------------------
-// NOTE: this header is still here just as a place-holder for
-//       Doxygen page about Sprites
-//------------------------------------------------------------------
-
-/// \page Sprite Sprites and MovieClips
-///
-/// A Sprite, or MovieClip, is a mini movie-within-a-movie. 
-///
-/// It doesn't define its own DisplayObjects;
-/// it uses the DisplayObjects from the parent
-/// movie, but it has its own frame counter, display list, etc.
-///
-/// @@ are we sure it doesn't define its own chars ?
-///
-/// The sprite implementation is divided into 
-/// gnash::sprite_definition and gnash::MovieClip.
-///
-/// The _definition holds the immutable data for a sprite (as read
-/// from an SWF stream), while the _instance contains the state for
-/// a specific run of if (frame being played, mouse state, timers,
-/// display list as updated by actions, ...)
-///
-

=== modified file 'libcore/StaticText.cpp'
--- a/libcore/StaticText.cpp    2009-04-03 11:03:31 +0000
+++ b/libcore/StaticText.cpp    2009-04-07 12:34:43 +0000
@@ -1,4 +1,4 @@
-// Shape.cpp:  Mouse/Character handling, for Gnash.
+// StaticText.cpp:  StaticText DisplayObject implementation for Gnash.
 // 
 //   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 // 
@@ -38,20 +38,19 @@
 }
 
 bool
-StaticText::pointInShape(boost::int32_t  x, boost::int32_t  y) const
+StaticText::pointInShape(boost::int32_t /*x*/, boost::int32_t /*y*/) const
 {
-    SWFMatrix wm = getWorldMatrix();
-    SWFMatrix wm_inverse = wm.invert();
-    point lp(x, y);
-    wm_inverse.transform(lp);
-    return _def->point_test_local(lp.x, lp.y, wm);
+    // TODO: this has never worked as it relied on the default
+    // pointTestLocal in DefinitionTag, which returned false. There are
+    // no tests for whether StaticText has a proper hit test.
+    return false;
 }
 
 
 void  
 StaticText::display()
 {
-    _def->display(this); // pass in transform info
+    _def->display(*this);
     clear_invalidated();
 }
 

=== modified file 'libcore/StaticText.h'
--- a/libcore/StaticText.h      2009-04-03 11:03:31 +0000
+++ b/libcore/StaticText.h      2009-04-07 12:34:43 +0000
@@ -1,3 +1,4 @@
+// StaticText.h:  StaticText DisplayObject implementation for Gnash.
 // 
 //   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 // 
@@ -28,7 +29,7 @@
 
 // Forward declarations
 namespace gnash {
-    class character_def;
+    class DefinitionTag;
     namespace SWF {
         class TextRecord;
     }
@@ -43,7 +44,8 @@
 {
 public:
 
-       StaticText(SWF::DefineTextTag* def, DisplayObject* parent, int id)
+       StaticText(const SWF::DefineTextTag* const def, DisplayObject* parent,
+            int id)
                :
         DisplayObject(parent, id),
         _def(def)
@@ -104,7 +106,7 @@
 
 private:
 
-    const boost::intrusive_ptr<SWF::DefineTextTag> _def;
+    const boost::intrusive_ptr<const SWF::DefineTextTag> _def;
 
     /// A bitmask indicating which static text DisplayObjects are selected
     //
@@ -123,7 +125,7 @@
 }      // end namespace gnash
 
 
-#endif // GNASH_GENERIC_CHARACTER_H
+#endif 
 
 
 // Local Variables:

=== modified file 'libcore/TextField.cpp'
--- a/libcore/TextField.cpp     2009-04-04 15:35:18 +0000
+++ b/libcore/TextField.cpp     2009-04-07 12:46:29 +0000
@@ -343,7 +343,7 @@
         m.concatenate_translation(_bounds.get_x_min(), _bounds.get_y_min()); 
     }
     
-    SWF::TextRecord::displayRecords(m, this, _textRecords, _embedFonts);
+    SWF::TextRecord::displayRecords(m, *this, _textRecords, _embedFonts);
 
     if (m_has_focus) show_cursor(wmat);
     
@@ -987,7 +987,7 @@
     int    last_space_glyph = -1;
     int    last_line_start_record = 0;
 
-    unsigned int DisplayObject_idx = 0;
+    unsigned int idx = 0;
     m_xcursor = x;
     m_ycursor = y;
 
@@ -1286,12 +1286,12 @@
         }
 
 
-        if (m_cursor > DisplayObject_idx)
+        if (m_cursor > idx)
         {
             m_xcursor = x;
             m_ycursor = y;
         }
-        DisplayObject_idx++;
+        idx++;
 
         // TODO: HTML markup
     }

=== modified file 'libcore/Video.cpp'
--- a/libcore/Video.cpp 2009-04-03 09:18:40 +0000
+++ b/libcore/Video.cpp 2009-04-06 11:16:20 +0000
@@ -263,8 +263,6 @@
 Video::advance()
 {
        if (_ns) {
-               //_ns->advance();
-        
         // NOTE: only needed for gstreamer:
                if (_ns->newFrameReady()) set_invalidated();
        }

=== modified file 'libcore/as_environment.cpp'
--- a/libcore/as_environment.cpp        2009-04-03 09:48:13 +0000
+++ b/libcore/as_environment.cpp        2009-04-07 09:49:53 +0000
@@ -20,7 +20,6 @@
 #include "smart_ptr.h" // GNASH_USE_GC
 #include "as_environment.h"
 #include "MovieClip.h"
-#include "shape_character_def.h"
 #include "as_value.h"
 #include "VM.h"
 #include "log.h"

=== modified file 'libcore/fill_style.h'
--- a/libcore/fill_style.h      2009-04-03 09:48:13 +0000
+++ b/libcore/fill_style.h      2009-04-06 08:16:33 +0000
@@ -253,7 +253,7 @@
        ///
        rgba sample_gradient(boost::uint8_t ratio) const;
 
-       friend class morph2_character_def;
+       friend class MorphShape;
 
        // For BITMAP or GRADIENT types 
        SWFMatrix       _matrix;

=== modified file 'libcore/fontlib.cpp'
--- a/libcore/fontlib.cpp       2008-11-14 00:46:35 +0000
+++ b/libcore/fontlib.cpp       2009-04-07 12:34:43 +0000
@@ -13,7 +13,7 @@
 #include "impl.h"
 #include "log.h"
 #include "render.h"
-#include "shape_character_def.h"
+#include "DefineShapeTag.h"
 #include "styles.h"
 #include "movie_definition.h"
 

=== modified file 'libcore/impl.cpp'
--- a/libcore/impl.cpp  2009-02-10 11:33:38 +0000
+++ b/libcore/impl.cpp  2009-04-07 12:45:25 +0000
@@ -36,6 +36,7 @@
 #include "ScriptLimitsTag.h"
 #include "BitmapMovieDefinition.h"
 #include "DefineFontAlignZonesTag.h"
+#include "DefineShapeTag.h"
 #include "DefineButtonCxformTag.h"
 #include "CSMTextSettingsTag.h"
 #include "DefineFontTag.h"
@@ -50,6 +51,7 @@
 #include "StartSoundTag.h"
 #include "StreamSoundBlockTag.h"
 #include "DefineButtonSoundTag.h"
+#include "DefineMorphShapeTag.h"
 #include "DefineVideoStreamTag.h"
 #include "DefineFontNameTag.h"
 #include "VideoFrameTag.h"
@@ -107,7 +109,7 @@
     // TODO: use null_loader here ?
     register_tag_loader(SWF::END, end_loader);
 
-    register_tag_loader(SWF::DEFINESHAPE, define_shape_loader);
+    register_tag_loader(SWF::DEFINESHAPE, DefineShapeTag::loader);
     register_tag_loader(SWF::FREECHARACTER, fixme_loader); // 03
     register_tag_loader(SWF::PLACEOBJECT, PlaceObject2Tag::loader);
     register_tag_loader(SWF::REMOVEOBJECT,  RemoveObjectTag::loader); // 05
@@ -136,7 +138,7 @@
     register_tag_loader(SWF::SOUNDSTREAMBLOCK, StreamSoundBlockTag::loader);
     register_tag_loader(SWF::DEFINELOSSLESS, define_bits_lossless_2_loader);
     register_tag_loader(SWF::DEFINEBITSJPEG2, define_bits_jpeg2_loader);
-    register_tag_loader(SWF::DEFINESHAPE2,  define_shape_loader);
+    register_tag_loader(SWF::DEFINESHAPE2,  DefineShapeTag::loader);
     register_tag_loader(SWF::DEFINEBUTTONCXFORM, 
DefineButtonCxformTag::loader); // 23
     // "protect" tag; we're not an authoring tool so we don't care.
     // (might be nice to dump the password instead..)
@@ -148,7 +150,7 @@
     register_tag_loader(SWF::SYNCFRAME, fixme_loader); // 29
     // 30 - _UNKNOWN_ unimplemented
     register_tag_loader(SWF::FREEALL, fixme_loader); // 31
-    register_tag_loader(SWF::DEFINESHAPE3,  define_shape_loader);
+    register_tag_loader(SWF::DEFINESHAPE3,  DefineShapeTag::loader);
     register_tag_loader(SWF::DEFINETEXT2, DefineText2Tag::loader);
     // 37
     register_tag_loader(SWF::DEFINEBUTTON2, DefineButton2Tag::loader);
@@ -166,7 +168,8 @@
     register_tag_loader(SWF::DEFINEBEHAVIOR, fixme_loader); // 44
 
     register_tag_loader(SWF::SOUNDSTREAMHEAD2, sound_stream_head_loader); // 45
-    register_tag_loader(SWF::DEFINEMORPHSHAPE, define_shape_morph_loader);
+    // 46
+    register_tag_loader(SWF::DEFINEMORPHSHAPE, DefineMorphShapeTag::loader);
     register_tag_loader(SWF::FRAMETAG,  fixme_loader); // 47
     // 48
     register_tag_loader(SWF::DEFINEFONT2, DefineFontTag::loader);
@@ -208,10 +211,11 @@
 
     // TODO: Alexis reference says these are 83, 84. The 67,68 comes from 
Tamarin.
     // Figure out which one is correct (possibly both are).
-    register_tag_loader(SWF::DEFINESHAPE4_, define_shape_loader); // 67
-    register_tag_loader(SWF::DEFINEMORPHSHAPE2_, define_shape_morph_loader); 
// 68
-
-    register_tag_loader(SWF::FILEATTRIBUTES, file_attributes_loader); // 69
+    register_tag_loader(SWF::DEFINESHAPE4_, DefineShapeTag::loader); // 67
+    // 68
+    register_tag_loader(SWF::DEFINEMORPHSHAPE2_, DefineMorphShapeTag::loader);
+    // 69
+    register_tag_loader(SWF::FILEATTRIBUTES, file_attributes_loader);
     register_tag_loader(SWF::PLACEOBJECT3, PlaceObject2Tag::loader); // 70
     register_tag_loader(SWF::IMPORTASSETS2, import_loader); // 71
 
@@ -225,8 +229,9 @@
     register_tag_loader(SWF::METADATA, metadata_loader); // 77
     register_tag_loader(SWF::DEFINESCALINGGRID, fixme_loader); // 78
     register_tag_loader(SWF::DOABCDEFINE, abc_loader); // 82 -- AS3 codeblock.
-    register_tag_loader(SWF::DEFINESHAPE4, define_shape_loader); // 83
-    register_tag_loader(SWF::DEFINEMORPHSHAPE2, define_shape_morph_loader); // 
84
+    register_tag_loader(SWF::DEFINESHAPE4, DefineShapeTag::loader); // 83
+    // 84
+    register_tag_loader(SWF::DEFINEMORPHSHAPE2, DefineMorphShapeTag::loader);
     
register_tag_loader(SWF::DEFINESCENEANDFRAMELABELDATA,define_scene_frame_label_loader);
 //86
     // 88
     register_tag_loader(SWF::DEFINEFONTNAME, DefineFontNameTag::loader);

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2009-04-04 20:08:19 +0000
+++ b/libcore/movie_root.cpp    2009-04-06 08:16:33 +0000
@@ -2037,8 +2037,7 @@
 void
 movie_root::advanceLiveChar(boost::intrusive_ptr<DisplayObject> ch)
 {
-
-       if ( ! ch->isUnloaded() )
+       if (!ch->isUnloaded())
        {
 #ifdef GNASH_DEBUG
                log_debug("    advancing DisplayObject %s", ch->getTarget());

=== modified file 'libcore/parser/BitmapMovieDefinition.cpp'
--- a/libcore/parser/BitmapMovieDefinition.cpp  2009-04-03 09:18:40 +0000
+++ b/libcore/parser/BitmapMovieDefinition.cpp  2009-04-07 12:34:43 +0000
@@ -25,29 +25,28 @@
 #include "render.h" // for ::display
 #include "GnashImage.h"
 #include "log.h"
+#include "Shape.h"
 
 namespace gnash {
 
-shape_character_def*
-BitmapMovieDefinition::getShapeDef()
+DisplayObject*
+BitmapMovieDefinition::createDisplayObject(DisplayObject* parent, int id)
 {
-       if ( _shapedef ) return _shapedef.get();
 
     // It's possible for this to fail.
     if (!_bitmap.get()) return 0;
 
-       // Create the shape definition
-       _shapedef = new DynamicShape();
+    if (!_shape.get()) _shape.reset(new DynamicShape);
 
        // Set its boundaries
-       _shapedef->set_bound(_framesize);
+       _shape->setBounds(_framesize);
 
        // Add the bitmap fill style (fill style 0)
 
        SWFMatrix mat;
        mat.set_scale(1.0/20, 1.0/20); // bitmap fills get SWFMatrix reversed
        fill_style bmFill(_bitmap.get(), mat);
-       const size_t fillLeft = _shapedef->add_fill_style(bmFill);
+       const size_t fillLeft = _shape->add_fill_style(bmFill);
 
        // Define a rectangle filled with the bitmap style
 
@@ -61,7 +60,7 @@
            log_parse(_("Creating a shape_definition wrapping a %g x %g 
bitmap"), w, h);
        );
 
-       path bmPath(w, h, fillLeft, 0, 0, false);
+       Path bmPath(w, h, fillLeft, 0, 0, false);
        bmPath.drawLineTo(w, 0);
        bmPath.drawLineTo(0, 0);
        bmPath.drawLineTo(0, h);
@@ -69,9 +68,9 @@
 
        // Add the path 
 
-       _shapedef->add_path(bmPath);
+       _shape->add_path(bmPath);
 
-       return _shapedef.get();
+       return new Shape(_shape, parent, id);
 }
 
 BitmapMovieDefinition::BitmapMovieDefinition(
@@ -87,15 +86,14 @@
        _bytesTotal(image->size()),
        _bitmap(render::createBitmapInfo(image))
 {
-       // Do not create shape_character_def now (why?)
+       // Do not create DefineShapeTag now (why?)
 }
 
 #ifdef GNASH_USE_GC
 void
 BitmapMovieDefinition::markReachableResources() const
 {
-       if ( _shapedef.get() ) _shapedef->setReachable();
-       if ( _bitmap.get() ) _bitmap->setReachable();
+       if (_bitmap.get()) _bitmap->setReachable();
 }
 #endif // GNASH_USE_GC
 

=== modified file 'libcore/parser/BitmapMovieDefinition.h'
--- a/libcore/parser/BitmapMovieDefinition.h    2009-04-03 09:18:40 +0000
+++ b/libcore/parser/BitmapMovieDefinition.h    2009-04-07 09:19:54 +0000
@@ -58,15 +58,7 @@
        BitmapMovieDefinition(std::auto_ptr<GnashImage> image,
             const std::string& url);
 
-    virtual DisplayObject* createDisplayObject(DisplayObject*, int) {
-        return 0;
-    }
-
-       // Discard id, always return the only shape DisplayObject we have 
-       virtual character_def* get_character_def(int /*id*/)
-       {
-               return getShapeDef();
-       }
+    virtual DisplayObject* createDisplayObject(DisplayObject*, int);
 
        virtual int     get_version() const {
                return _version;
@@ -160,13 +152,7 @@
 
     boost::intrusive_ptr<BitmapInfo> _bitmap;
 
-       boost::intrusive_ptr<DynamicShape> _shapedef;
-
-       /// Get the shape DisplayObject definition for this bitmap movie
-       //
-       /// It will create the definition the first time it's called
-       ///
-       shape_character_def* getShapeDef();
+    boost::shared_ptr<DynamicShape> _shape;
 
 };
 

=== modified file 'libcore/parser/Makefile.am'
--- a/libcore/parser/Makefile.am        2009-02-27 06:46:40 +0000
+++ b/libcore/parser/Makefile.am        2009-04-07 12:34:43 +0000
@@ -47,23 +47,17 @@
        abc_block.cpp \
        action_buffer.cpp \
        BitmapMovieDefinition.cpp \
-       character_def.cpp \
        SWFMovieDefinition.cpp \
-        morph2_character_def.cpp \
-       shape_character_def.cpp \
        sound_definition.cpp \
        sprite_definition.cpp
 
 noinst_HEADERS = \
        abc_block.h \
        action_buffer.h \
-       character_def.h \
        BitmapMovieDefinition.h \
-       morph2_character_def.h \
        movie_definition.h \
        SWFMovieDefinition.h \
        Namespace.h \
-       shape_character_def.h \
        sound_definition.h \
        sprite_definition.h
 

=== modified file 'libcore/parser/SWFMovieDefinition.cpp'
--- a/libcore/parser/SWFMovieDefinition.cpp     2009-04-03 09:48:13 +0000
+++ b/libcore/parser/SWFMovieDefinition.cpp     2009-04-07 12:52:56 +0000
@@ -226,21 +226,21 @@
        //assert(m_jpeg_in->get() == NULL);
 }
 
-void SWFMovieDefinition::addDisplayObject(int DisplayObject_id, character_def* 
c)
+void SWFMovieDefinition::addDisplayObject(int id, SWF::DefinitionTag* c)
 {
        assert(c);
        boost::mutex::scoped_lock lock(_dictionaryMutex);
-       _dictionary.addDisplayObject(DisplayObject_id, c);
+       _dictionary.addDisplayObject(id, c);
 }
 
-character_def*
-SWFMovieDefinition::get_character_def(int DisplayObject_id)
+SWF::DefinitionTag*
+SWFMovieDefinition::getDefinitionTag(int id)
 {
 
        boost::mutex::scoped_lock lock(_dictionaryMutex);
 
-       boost::intrusive_ptr<character_def> ch = 
-        _dictionary.getDisplayObject(DisplayObject_id);
+       boost::intrusive_ptr<SWF::DefinitionTag> ch = 
+        _dictionary.getDisplayObject(id);
 #ifndef GNASH_USE_GC
        assert(ch == NULL || ch->get_ref_count() > 1);
 #endif 
@@ -277,9 +277,9 @@
 }
 
 BitmapInfo*
-SWFMovieDefinition::getBitmap(int DisplayObject_id)
+SWFMovieDefinition::getBitmap(int id)
 {
-    Bitmaps::iterator it = _bitmaps.find(DisplayObject_id);
+    Bitmaps::iterator it = _bitmaps.find(id);
     if (it == _bitmaps.end()) return 0;
     
     return it->second.get();
@@ -293,9 +293,9 @@
 
 }
 
-sound_sample* SWFMovieDefinition::get_sound_sample(int DisplayObject_id)
+sound_sample* SWFMovieDefinition::get_sound_sample(int id)
 {
-    SoundSampleMap::iterator it = m_sound_samples.find(DisplayObject_id);
+    SoundSampleMap::iterator it = m_sound_samples.find(id);
     if ( it == m_sound_samples.end() ) return NULL;
 
     boost::intrusive_ptr<sound_sample> ch = it->second;
@@ -306,14 +306,14 @@
     return ch.get();
 }
 
-void SWFMovieDefinition::add_sound_sample(int DisplayObject_id, sound_sample* 
sam)
+void SWFMovieDefinition::add_sound_sample(int id, sound_sample* sam)
 {
     assert(sam);
     IF_VERBOSE_PARSE(
     log_parse(_("Add sound sample %d assigning id %d"),
-               DisplayObject_id, sam->m_sound_handler_id);
+               id, sam->m_sound_handler_id);
     )
-    m_sound_samples.insert(std::make_pair(DisplayObject_id,
+    m_sound_samples.insert(std::make_pair(id,
                            boost::intrusive_ptr<sound_sample>(sam)));
 }
 
@@ -510,7 +510,7 @@
        return o;
 }
 
-boost::intrusive_ptr<character_def>
+boost::intrusive_ptr<SWF::DefinitionTag>
 CharacterDictionary::getDisplayObject(int id)
 {
        CharacterIterator it = _map.find(id);
@@ -519,7 +519,7 @@
                IF_VERBOSE_PARSE(
             log_parse(_("Could not find char %d, dump is: %s"), id, *this);
                );
-               return boost::intrusive_ptr<character_def>();
+               return boost::intrusive_ptr<SWF::DefinitionTag>();
        }
        
     return it->second;
@@ -527,7 +527,7 @@
 
 void
 CharacterDictionary::addDisplayObject(int id,
-        boost::intrusive_ptr<character_def> c)
+        boost::intrusive_ptr<SWF::DefinitionTag> c)
 {
        //log_debug(_("CharacterDictionary: add char %d"), id);
        _map[id] = c;
@@ -927,7 +927,7 @@
                        add_font(id, f);
                        ++importedSyms;
         }
-        else if (character_def* ch = dynamic_cast<character_def*>(res.get()))
+        else if (SWF::DefinitionTag* ch = 
dynamic_cast<SWF::DefinitionTag*>(res.get()))
         {
             // Add this DisplayObject to the loading movie.
             addDisplayObject(id, ch);

=== modified file 'libcore/parser/SWFMovieDefinition.h'
--- a/libcore/parser/SWFMovieDefinition.h       2009-04-03 09:48:13 +0000
+++ b/libcore/parser/SWFMovieDefinition.h       2009-04-07 12:46:29 +0000
@@ -31,7 +31,7 @@
 #include "GnashImageJpeg.h"
 #include "IOChannel.h"
 #include "movie_definition.h" // for inheritance
-#include "character_def.h" // for boost::intrusive_ptr visibility of dtor
+#include "DefinitionTag.h" // for boost::intrusive_ptr visibility of dtor
 #include "StringPredicates.h" 
 #include "rect.h"
 #include "GnashNumeric.h"
@@ -117,9 +117,9 @@
 
        /// The container used by this dictionary
        //
-       /// It contains pairs of 'int' and 'boost::intrusive_ptr<character_def>'
+       /// It contains pairs of 'int' and 'boost::intrusive_ptr<DefinitionTag>'
        ///
-       typedef std::map<int, boost::intrusive_ptr<character_def> >
+       typedef std::map<int, boost::intrusive_ptr<SWF::DefinitionTag> >
         CharacterContainer;
 
        typedef CharacterContainer::iterator CharacterIterator;
@@ -130,13 +130,13 @@
        //
        /// returns a NULL if the id is unknown.
        ///
-       boost::intrusive_ptr<character_def> getDisplayObject(int id);
+       boost::intrusive_ptr<SWF::DefinitionTag> getDisplayObject(int id);
 
        /// Add a Character assigning it the given id
        //
        /// replaces any existing DisplayObject with the same id
        ///
-       void addDisplayObject(int id, boost::intrusive_ptr<character_def> c);
+       void addDisplayObject(int id, boost::intrusive_ptr<SWF::DefinitionTag> 
c);
 
        /// Return an iterator to the first dictionary element
        CharacterIterator begin() { return _map.begin(); }
@@ -246,14 +246,14 @@
        virtual void importResources(boost::intrusive_ptr<movie_definition> 
source,
             Imports& imports);
 
-       void addDisplayObject(int DisplayObject_id, character_def* c);
+       void addDisplayObject(int DisplayObject_id, SWF::DefinitionTag* c);
 
        /// \brief
        /// Return a DisplayObject from the dictionary
        /// NOTE: call add_ref() on the return or put in a 
boost::intrusive_ptr<>
        /// TODO: return a boost::intrusive_ptr<> directly...
        ///
-       character_def*  get_character_def(int DisplayObject_id);
+    SWF::DefinitionTag* getDefinitionTag(int DisplayObject_id);
 
        // See dox in movie_definition
        //
@@ -395,7 +395,7 @@
     // It is required that get_bound() is implemented in DisplayObject 
definition
     // classes. However, it makes no sense to call it for movie interfaces.
     // get_bound() is currently only used by DisplayObject which normally
-    // is used only shape DisplayObject definitions. See character_def.h to 
learn
+    // is used only shape DisplayObject definitions. See DefinitionTag.h to 
learn
     // why it is virtual anyway.
     abort(); // should not be called  
                static rect unused;

=== removed file 'libcore/parser/character_def.cpp'
--- a/libcore/parser/character_def.cpp  2009-03-10 20:43:50 +0000
+++ b/libcore/parser/character_def.cpp  1970-01-01 00:00:00 +0000
@@ -1,39 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-#ifdef HAVE_CONFIG_H
-#include "gnashconfig.h"
-#endif
-
-#include "character_def.h"
-#include "render_handler.h" // for destruction of render_cache_manager
-
-namespace gnash
-{
-
-character_def::~character_def()
-{
-       delete m_render_cache;
-}
-
-} // end of namespace gnash
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:

=== modified file 'libcore/parser/movie_definition.h'
--- a/libcore/parser/movie_definition.h 2009-04-03 09:48:13 +0000
+++ b/libcore/parser/movie_definition.h 2009-04-07 13:13:16 +0000
@@ -51,7 +51,7 @@
 #include "gnashconfig.h" // for USE_SWFTREE
 #endif
 
-#include "character_def.h" // for inheritance
+#include "swf/DefinitionTag.h"
 #include "GnashImageJpeg.h"
 
 #include <string>
@@ -78,7 +78,7 @@
 /// This is the shared constant source info, the one that cannot
 /// be changed by ActionScript code.
 ///
-/// The class derives from character_def to allow a movie
+/// The class derives from DefinitionTag to allow a movie
 /// to be put in the CharacterDictionary. This is probably
 /// unneeded for top-level movies, because they don't need
 /// to be put in any CharacterDictionary... anyway the
@@ -90,10 +90,10 @@
 /// This design is uncomfortable when it comes to programmatically
 /// created DisplayObjects, in that they do NOT have any *fixed* definition.
 /// A possible workaround to this would be not *requiring* DisplayObject
-/// instances to have an associated character_def. I'll work on this
+/// instances to have an associated DefinitionTag. I'll work on this
 /// --strk 2006-12-05.
 ///
-class movie_definition : public character_def
+class movie_definition : public SWF::DefinitionTag
 {
 public:
        typedef std::vector<ControlTag*> PlayList;
@@ -195,7 +195,7 @@
        /// @return NULL if no DisplayObject with the given ID is found
        ///         (this is the default)
        ///
-       virtual character_def*  get_character_def(int /*id*/)
+       virtual DefinitionTag*  getDefinitionTag(int /*id*/)
        {
                return NULL;
        }
@@ -232,7 +232,7 @@
        /// This method is here to be called by DEFINE tags loaders.
        /// The default implementation does nothing.
        ///
-       virtual void addDisplayObject(int /*id*/, character_def* /*ch*/)
+       virtual void addDisplayObject(int /*id*/, DefinitionTag* /*ch*/)
        {
        }
 
@@ -445,7 +445,7 @@
 
        virtual const std::string& getDescriptiveMetadata() const
        {
-           static const std::string s("");
+           static const std::string s;
            return s;
        }       
 

=== modified file 'libcore/parser/sprite_definition.cpp'
--- a/libcore/parser/sprite_definition.cpp      2009-04-03 09:18:40 +0000
+++ b/libcore/parser/sprite_definition.cpp      2009-04-06 11:16:20 +0000
@@ -52,10 +52,10 @@
 sprite_definition::~sprite_definition()
 {
        // Release our playlist data.
-       for (PlayListMap::iterator i=m_playlist.begin(), e=m_playlist.end(); 
i!=e; ++i)
+       for (PlayListMap::iterator i=m_playlist.begin(), e=m_playlist.end();
+            i != e; ++i)
        {
                PlayList& pl = i->second;
-
         deleteAllChecked(pl);
     }
 }

=== modified file 'libcore/parser/sprite_definition.h'
--- a/libcore/parser/sprite_definition.h        2009-04-03 09:48:13 +0000
+++ b/libcore/parser/sprite_definition.h        2009-04-07 12:51:13 +0000
@@ -169,7 +169,7 @@
        virtual void addBitmap(int /*id*/, boost::intrusive_ptr<BitmapInfo> 
/*im*/)
        {
                IF_VERBOSE_MALFORMED_SWF (
-               log_swferror(_("add_bitmap_character_def appears in sprite 
tags"));
+               log_swferror(_("add_bitmap_SWF::DefinitionTag appears in sprite 
tags"));
                );
        }
 
@@ -224,16 +224,16 @@
        }
 
        /// \brief
-       /// Get a character_def from this Sprite's root movie
+       /// Get a SWF::DefinitionTag from this Sprite's root movie
        /// CharacterDictionary.
        ///
-       virtual character_def*  get_character_def(int id)
+       virtual SWF::DefinitionTag*     getDefinitionTag(int id)
        {
-           return m_movie_def.get_character_def(id);
+           return m_movie_def.getDefinitionTag(id);
        }
 
        /// Delegate call to associated root movie
-       virtual void addDisplayObject(int id, character_def* ch)
+       virtual void addDisplayObject(int id, SWF::DefinitionTag* ch)
        {
                m_movie_def.addDisplayObject(id, ch);
        }
@@ -242,7 +242,7 @@
        // instance is created to live (temporarily) on some level on
        // the parent movie's display list.
        //
-       // overloads from character_def
+       // overloads from SWF::DefinitionTag
        virtual DisplayObject* createDisplayObject(DisplayObject* parent, int 
id);
 
 
@@ -326,7 +326,7 @@
     // It is required that get_bound() is implemented in DisplayObject 
definition
     // classes. However, it makes no sense to call it for sprite definitions.
     // get_bound() is currently only used by DisplayObject which normally
-    // is used only shape DisplayObject definitions. See character_def.h to 
learn
+    // is used only shape DisplayObject definitions. See SWF::DefinitionTag.h 
to learn
     // why it is virtual anyway.
     abort(); // should not be called
                static rect unused;

=== modified file 'libcore/render.cpp'
--- a/libcore/render.cpp        2009-04-03 09:18:40 +0000
+++ b/libcore/render.cpp        2009-04-07 14:32:06 +0000
@@ -151,22 +151,23 @@
 }
 
 
-void drawShape(shape_character_def *def, DisplayObject *inst) 
+void
+drawShape(const SWF::ShapeRecord& shape, const cxform& cx,
+        const SWFMatrix& worldMat)
 {
 #ifdef DEBUG_RENDER_CALLS
                GNASH_REPORT_FUNCTION;
 #endif
-               if (s_render_handler) s_render_handler->drawShape(def, inst);
+               if (s_render_handler) s_render_handler->drawShape(shape, cx, 
worldMat);
 }
 
-void draw_glyph(shape_character_def *def,
-  const SWFMatrix& mat,
-  const rgba& color)
+void drawGlyph(const SWF::ShapeRecord& rec, const rgba& color, 
+      const SWFMatrix& mat)
 {
 #ifdef DEBUG_RENDER_CALLS
                GNASH_REPORT_FUNCTION;
 #endif
-               if (s_render_handler) s_render_handler->draw_glyph(def, mat, 
color);
+               if (s_render_handler) s_render_handler->drawGlyph(rec, color, 
mat);
 }
 
 bool bounds_in_clipping_area(const rect& bounds) {

=== modified file 'libcore/render.h'
--- a/libcore/render.h  2009-04-03 09:48:13 +0000
+++ b/libcore/render.h  2009-04-07 14:32:06 +0000
@@ -30,6 +30,9 @@
 namespace gnash {
     class rgba;
     class GnashImage;
+    namespace SWF {
+        class ShapeRecord;
+    }
 }
 
 namespace gnash {
@@ -78,13 +81,13 @@
                DSOEXPORT void  draw_poly(const point* corners, int 
corner_count,
                                const rgba& fill, const rgba& outline, const 
SWFMatrix& mat,
                                bool masked);
-      
-               /// See render_handler::draw_Shape (in backend/render_handler.h)
-               void drawShape(shape_character_def *def, DisplayObject *inst);
+        
+        void drawShape(const SWF::ShapeRecord& shape, const cxform& cx,
+                const SWFMatrix& worldMat);
       
                /// See render_handler::draw_glyph (in backend/render_handler.h)
-               void draw_glyph(shape_character_def *def, const SWFMatrix& mat,
-                               const rgba& color);
+               void drawGlyph(const SWF::ShapeRecord& rec, const rgba& color,
+                const SWFMatrix& mat);
 
                /// See render_handler::bounds_in_clipping_area (in 
backend/render_handler.h)
                bool bounds_in_clipping_area(const rect& bounds);

=== modified file 'libcore/swf/DefineButtonCxformTag.cpp'
--- a/libcore/swf/DefineButtonCxformTag.cpp     2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineButtonCxformTag.cpp     2009-04-07 12:46:29 +0000
@@ -40,7 +40,7 @@
         log_debug("DefineButtonCxformTag: ButtonId=%d", buttonID);
     );
     
-    character_def* chdef = m.get_character_def(buttonID);
+    DefinitionTag* chdef = m.getDefinitionTag(buttonID);
     if (!chdef)
     {
         IF_VERBOSE_MALFORMED_SWF(

=== modified file 'libcore/swf/DefineButtonSoundTag.cpp'
--- a/libcore/swf/DefineButtonSoundTag.cpp      2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineButtonSoundTag.cpp      2009-04-07 12:46:29 +0000
@@ -43,7 +43,7 @@
 
     in.ensureBytes(2);
     int id = in.read_u16();
-    character_def* chdef = m.get_character_def(id);
+    DefinitionTag* chdef = m.getDefinitionTag(id);
     if (!chdef)
     {
         IF_VERBOSE_MALFORMED_SWF(

=== modified file 'libcore/swf/DefineButtonTag.cpp'
--- a/libcore/swf/DefineButtonTag.cpp   2009-04-03 09:48:13 +0000
+++ b/libcore/swf/DefineButtonTag.cpp   2009-04-07 12:46:29 +0000
@@ -103,7 +103,7 @@
 bool
 ButtonRecord::is_valid()
 {
-       return (m_character_def != NULL);
+       return (m_DefinitionTag != NULL);
 }
 
 static std::string
@@ -159,11 +159,11 @@
        _id = in.read_u16();
 
        // Get DisplayObject definition now (safer)
-       m_character_def = m.get_character_def(_id);
+       m_DefinitionTag = m.getDefinitionTag(_id);
 
        // If no DisplayObject with given ID is found in the movie
        // definition, we print an error, but keep parsing.
-       if (!m_character_def)
+       if (!m_DefinitionTag)
        {
                IF_VERBOSE_MALFORMED_SWF(
                log_swferror(_("   button record for states [%s] refer to "
@@ -176,7 +176,7 @@
                IF_VERBOSE_PARSE(
                log_parse(_("   button record for states [%s] contain "
                        "DisplayObject %d (%s)"), 
computeButtonStatesString(flags),
-            _id, typeName(*m_character_def));
+            _id, typeName(*m_DefinitionTag));
                );
        }
 

=== modified file 'libcore/swf/DefineButtonTag.h'
--- a/libcore/swf/DefineButtonTag.h     2009-04-03 09:48:13 +0000
+++ b/libcore/swf/DefineButtonTag.h     2009-04-07 12:34:43 +0000
@@ -21,7 +21,7 @@
 #define GNASH_SWF_DEFINEBUTTONTAG_H
 
 #include "smart_ptr.h" // GNASH_USE_GC
-#include "character_def.h"
+#include "DefinitionTag.h"
 #include "sound_definition.h"
 #include "rect.h" // for get_bound
 #include "SWFMatrix.h" // for composition
@@ -78,7 +78,7 @@
        int     _id;
 
        // Who owns this ?
-       character_def* m_character_def;
+       DefinitionTag* m_DefinitionTag;
 
        int     m_button_layer;
        SWFMatrix       m_button_matrix;
@@ -89,7 +89,7 @@
 
        ButtonRecord()
                :
-               m_character_def(0)
+               m_DefinitionTag(0)
        {
        }
 
@@ -113,11 +113,11 @@
        /// Mark all reachable resources (for GC)
        //
        /// Reachable resources are:
-       ///  - m_character_def (??) what's it !?
+       ///  - m_DefinitionTag (??) what's it !?
        ///
        void markReachableResources() const
        {
-               if ( m_character_def ) m_character_def->setReachable();
+               if ( m_DefinitionTag ) m_DefinitionTag->setReachable();
        }
 #endif // GNASH_USE_GC
 
@@ -179,7 +179,7 @@
 };
 
 /// A class for parsing DefineButton and DefineButton2 tags.
-class DefineButtonTag : public character_def
+class DefineButtonTag : public DefinitionTag
 {
 public:
 
@@ -199,9 +199,9 @@
                // It is required that get_bound() is implemented in 
DisplayObject
         // definition classes. However, button DisplayObject definitions do
         // not have shape definitions themselves. Instead, they hold a list
-        // of shape_character_def. get_bound() is currently only used
+        // of DefineShapeTag. get_bound() is currently only used
         // by DisplayObject which normally is used only shape DisplayObject
-        // definitions. See character_def.h to learn why it is virtual anyway.
+        // definitions. See DefinitionTag.h to learn why it is virtual anyway.
                // get_button_bound() is used for buttons.
                abort(); // should not be called  
                static rect unused;

=== modified file 'libcore/swf/DefineEditTextTag.h'
--- a/libcore/swf/DefineEditTextTag.h   2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineEditTextTag.h   2009-04-07 12:34:43 +0000
@@ -23,7 +23,7 @@
 #endif
 
 #include "rect.h"
-#include "character_def.h"
+#include "DefinitionTag.h"
 #include "swf.h" // for TagType definition
 #include "RGBA.h"
 #include "TextField.h"
@@ -54,7 +54,7 @@
 /// The tag will then be used to start playing the specific block
 /// in sync with the frame playhead.
 ///
-class DefineEditTextTag : public character_def
+class DefineEditTextTag : public DefinitionTag
 {
 
 public:

=== modified file 'libcore/swf/DefineFontTag.cpp'
--- a/libcore/swf/DefineFontTag.cpp     2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineFontTag.cpp     2009-04-07 11:14:10 +0000
@@ -23,7 +23,7 @@
 #include "RunInfo.h"
 #include "swf.h"
 #include "movie_definition.h"
-#include "shape_character_def.h"
+#include "ShapeRecord.h"
 
 // Based on the public domain work of Thatcher Ulrich <address@hidden> 2003
 
@@ -175,10 +175,7 @@
         }
 
         // Create & read the shape.
-        shape_character_def* s = new shape_character_def;
-        s->read(in, SWF::DEFINEFONT, false, m); 
-
-        _glyphTable[i].glyph = s;
+        _glyphTable[i].glyph.reset(new ShapeRecord(in, SWF::DEFINEFONT, m)); 
     }
 }
 
@@ -280,14 +277,12 @@
 
         if ( ! in.seek(new_pos) )
         {
-            throw ParserException(_("Glyphs offset table corrupted in 
DefineFont2/3 tag"));
+            throw ParserException(_("Glyphs offset table corrupted in "
+                        "DefineFont2/3 tag"));
         }
 
         // Create & read the shape.
-        shape_character_def* s = new shape_character_def;
-        s->read(in, SWF::DEFINEFONT2, false, m); // .. or DEFINEFONT3 
actually..
-
-        _glyphTable[i].glyph = s;
+        _glyphTable[i].glyph.reset(new ShapeRecord(in, SWF::DEFINEFONT2, m));
     }
 
     unsigned long current_position = in.tell();

=== renamed file 'libcore/parser/morph2_character_def.cpp' => 
'libcore/swf/DefineMorphShapeTag.cpp'
--- a/libcore/parser/morph2_character_def.cpp   2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineMorphShapeTag.cpp       2009-04-07 14:32:06 +0000
@@ -1,4 +1,4 @@
-// morph2_character_def.cpp:   Load and render morphing shapes, for Gnash.
+// DefineMorphShapeTag.cpp:   Load and parse morphing shapes, for Gnash.
 //
 //   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 //
@@ -18,11 +18,12 @@
 //
 
 
-// Based on the public domain morph2.cpp of:
+// Based on the public domain morph.cpp of:
 // Thatcher Ulrich <address@hidden>, Mike Shaver <address@hidden> 2003,
 // Vitalij Alexeev <address@hidden> 2004.
 
-#include "morph2_character_def.h"
+#include "DefineMorphShapeTag.h"
+#include "MorphShape.h"
 #include "SWFStream.h"
 #include "render.h"
 #include "movie_definition.h"
@@ -30,210 +31,64 @@
 #include "GnashNumeric.h"
 
 namespace gnash {
-
-/// Functors for path and style manipulation.
-namespace {
-
-template<typename T>
-class Lerp
-{
-public:
-    Lerp(typename T::const_iterator style1, typename T::const_iterator style2,
-            const double ratio)
-        :
-        _style1(style1),
-        _style2(style2),
-        _ratio(ratio)
-    {}
-
-    void operator()(typename T::value_type& st)
-    {
-        st.set_lerp(*_style1, *_style2, _ratio);
-        ++_style1, ++_style2;
-    }
-
-private:
-    typename T::const_iterator _style1;
-    typename T::const_iterator _style2;
-    const double _ratio;
-};
-
-// Facilities for working with list of paths.
-class PathList
-{
-    typedef shape_character_def::Paths Paths;
-public:
-
-       PathList(const Paths& paths)
-               :
-               _paths(paths),
-               _currpath(0),
-               _curredge(0),
-               _nedges(computeNumberOfEdges(_paths))
-       {}
-
-       /// Return number of edges in the path list
-       size_t size() const
-       {
-               return _nedges;
-       }
-
-       /// Get next edge in the path list.
-       //
-       /// After last edge in the list has been fetched,
-       /// next call to this function will return first
-       /// edge again.
-       ///
-       const edge& getNextEdge()
-       {
-               const edge& ret = _paths[_currpath][_curredge];
-        if ( ++_curredge >= _paths[_currpath].size() )
-               {
-                       if ( ++_currpath >= _paths.size() )
-                       {
-                // this is not really needed,
-                               // but it's simpler to do so that
-                               // to make next call fail or abort..
-                               _currpath = 0;
-                               _curredge = 0;
-                       }
-               }
-               return ret;
-       }
-
-       /// Compute total number of edges
-       static size_t computeNumberOfEdges(const Paths& paths)
-       {
-               size_t count=0;
-               for (Paths::const_iterator i = paths.begin(), e = paths.end();
-                i != e; ++i) {
-
-                       count += i->size();
-               }
-               return count;
-       }
-
-private:
-
-       const Paths& _paths;
-
-       size_t _currpath;
-
-       size_t _curredge;
-
-       size_t _nedges;
-
-};
-
-} // anonymous namespace
-
-morph2_character_def::morph2_character_def()
-    :
-    m_shape1(new shape_character_def),
-    m_shape2(new shape_character_def)
-{
-}
-
-
-morph2_character_def::~morph2_character_def()
-{
-}
-
-void
-morph2_character_def::display(DisplayObject* inst)
-{
-
-    const double ratio = inst->get_ratio() / 65535.0;
-
-    // bounds
-    rect new_bound;
-    new_bound.set_lerp(m_shape1->get_bound(), m_shape2->get_bound(), ratio);
-    set_bound(new_bound);
-
-    // fill styles
-    const FillStyles::const_iterator fs1 = m_shape1->fillStyles().begin();
-    const FillStyles::const_iterator fs2 = m_shape2->fillStyles().begin();
-
-    std::for_each(_fill_styles.begin(), _fill_styles.end(),
-            Lerp<FillStyles>(fs1, fs2, ratio));
-
-    // line styles
-    const LineStyles::const_iterator ls1 = m_shape1->lineStyles().begin();
-    const LineStyles::const_iterator ls2 = m_shape2->lineStyles().begin();
-
-    std::for_each(_line_styles.begin(), _line_styles.end(),
-            Lerp<LineStyles>(ls1, ls2, ratio));
-
-    // This is used for cases in which number
-    // of paths in start shape and end shape are not
-    // the same.
-    path empty_path;
-    edge empty_edge;
-
-    // shape
-    const Paths& paths1 = m_shape1->paths();
-    const Paths& paths2 = m_shape2->paths();
-    for (size_t i = 0, k = 0, n = 0; i < _paths.size(); i++)
-    {
-        path& p = _paths[i];
-        const path& p1 = i < paths1.size() ? paths1[i] : empty_path;
-        const path& p2 = n < paths2.size() ? paths2[n] : empty_path;
-
-        const float new_ax = flerp(p1.ap.x, p2.ap.x, ratio);
-        const float new_ay = flerp(p1.ap.y, p2.ap.y, ratio);
-
-        p.reset(new_ax, new_ay, p1.getLeftFill(),
-                p2.getRightFill(), p1.getLineStyle());
-
-        //  edges;
-        const size_t len = p1.size();
-        p.m_edges.resize(len);
-
-        for (size_t j=0; j < p.size(); j++)
-        {
-            edge& e = p[j];
-            const edge& e1 = j < p1.size() ? p1[j] : empty_edge;
-            const edge& e2 = k < p2.size() ? p2[k] : empty_edge;
-
-            e.cp.x = static_cast<int>(flerp(e1.cp.x, e2.cp.x, ratio));
-            e.cp.y = static_cast<int>(flerp(e1.cp.y, e2.cp.y, ratio));
-            e.ap.x = static_cast<int>(flerp(e1.ap.x, e2.ap.x, ratio));
-            e.ap.y = static_cast<int>(flerp(e1.ap.y, e2.ap.y, ratio));
-            ++k;
-
-            if (p2.size() <= k) {
-                k = 0;
-                ++n;
-            }
-        }
-    }
-
-    //  display
-    render::drawShape(this, inst);
-
-}
-
-
-void morph2_character_def::read(SWFStream& in, SWF::TagType tag,
-        movie_definition& md)
-{
-    assert(tag == SWF::DEFINEMORPHSHAPE
-        || tag == SWF::DEFINEMORPHSHAPE2
-        || tag == SWF::DEFINEMORPHSHAPE2_);
-
-    rect bound1, bound2;
-    bound1.read(in);
-    bound2.read(in);
-
-    if (tag == SWF::DEFINEMORPHSHAPE2 || tag == SWF::DEFINEMORPHSHAPE2_) {
+namespace SWF {
+
+void
+DefineMorphShapeTag::loader(SWFStream& in, TagType tag, movie_definition& md,
+        const RunInfo& /*r*/)
+{
+    in.ensureBytes(2);
+    boost::uint16_t id = in.read_u16();
+
+    IF_VERBOSE_PARSE(
+            log_parse("DefineMorphShapeTag: id = %d", id);
+    );
+
+    DefineMorphShapeTag* morph = new DefineMorphShapeTag(in, tag, md);
+    md.addDisplayObject(id, morph);
+}
+
+DefineMorphShapeTag::DefineMorphShapeTag(SWFStream& in, TagType tag,
+        movie_definition& md)
+{
+    read(in, tag, md);
+}
+
+DisplayObject*
+DefineMorphShapeTag::createDisplayObject(DisplayObject* parent, int id)
+{
+    return new MorphShape(this, parent, id);
+}
+
+void
+DefineMorphShapeTag::display(const MorphShape& inst) const
+{
+    render::drawShape(inst.shape(), inst.get_world_cxform(),
+            inst.getWorldMatrix());
+}
+
+
+void
+DefineMorphShapeTag::read(SWFStream& in, TagType tag,
+        movie_definition& md)
+{
+    assert(tag == DEFINEMORPHSHAPE
+        || tag == DEFINEMORPHSHAPE2
+        || tag == DEFINEMORPHSHAPE2_);
+
+    rect bounds1, bounds2;
+    bounds1.read(in);
+    bounds2.read(in);
+
+    if (tag == DEFINEMORPHSHAPE2 || tag == DEFINEMORPHSHAPE2_) {
         // TODO: Use these values.
-        rect inner_bound1, inner_bound2;
-        inner_bound1.read(in);
-        inner_bound2.read(in);
+        rect innerBound1, innerBound2;
+        innerBound1.read(in);
+        innerBound2.read(in);
+
         // This should be used -- first 6 bits reserved, then
         // 'non-scaling' stroke, then 'scaling' stroke -- these can be
         // used to optimize morphing.
-        
         in.ensureBytes(1);
         static_cast<void>(in.read_u8());
     }
@@ -248,56 +103,45 @@
     fill_style fs1, fs2;
     for (size_t i = 0; i < fillCount; ++i) {
         fs1.read(in, tag, md, &fs2);
-        m_shape1->addFillStyle(fs1);
-        m_shape2->addFillStyle(fs2);
+        _shape1.addFillStyle(fs1);
+        _shape2.addFillStyle(fs2);
     }
 
     const boost::uint16_t lineCount = in.read_variable_count();
     line_style ls1, ls2;
     for (size_t i = 0; i < lineCount; ++i) {
         ls1.read_morph(in, tag, md, &ls2);
-        m_shape1->addLineStyle(ls1);
-        m_shape2->addLineStyle(ls2);
+        _shape1.addLineStyle(ls1);
+        _shape2.addLineStyle(ls2);
     }
 
-    m_shape1->read(in, tag, false, md);
+    _shape1.read(in, tag, md);
     in.align();
-    m_shape2->read(in, tag, false, md);
+    _shape2.read(in, tag, md);
 
     // Set bounds as read in *this* tags rather then
-    // the one computed from shape_character_def parser
+    // the one computed from ShapeRecord parser
     // (does it make sense ?)
-    m_shape1->set_bound(bound1);
-    m_shape2->set_bound(bound2);
-
-    const shape_character_def::FillStyles& s1Fills = m_shape1->fillStyles();
-
-    const shape_character_def::LineStyles& s1Lines = m_shape1->lineStyles();
-
-    assert(s1Fills.size() == m_shape2->fillStyles().size());
-    assert(s1Lines.size() == m_shape2->lineStyles().size());
-
-    // setup array size
-    _fill_styles.resize(s1Fills.size());
-    FillStyles::const_iterator s1 = s1Fills.begin();
-    for (FillStyles::iterator i = _fill_styles.begin(), e = _fill_styles.end();
-            i != e; ++i, ++s1) {
-
-        i->m_gradients.resize(s1->m_gradients.size());
-    }
-
-    _line_styles.resize(s1Lines.size());
-    _paths.resize(m_shape1->paths().size());
-
-    const unsigned edges1 = PathList::computeNumberOfEdges(m_shape1->paths());
-    const unsigned edges2 = PathList::computeNumberOfEdges(m_shape2->paths());
+    _shape1.setBounds(bounds1);
+    _shape2.setBounds(bounds2);
+    
+    // Starting bounds are the same as shape1
+    _bounds = bounds1;
+
+    assert(_shape1.fillStyles().size() == _shape2.fillStyles().size());
+    assert(_shape1.lineStyles().size() == _shape2.lineStyles().size());
+
+#if 0
+
+    const unsigned edges1 = PathList::computeNumberOfEdges(_shape1.paths());
+    const unsigned edges2 = PathList::computeNumberOfEdges(_shape2.paths());
 
     IF_VERBOSE_PARSE(
       log_parse("morph: "
           "startShape(paths:%d, edges:%u), "
           "endShape(paths:%d, edges:%u)",
-          m_shape1->paths().size(), edges1,
-          m_shape2->paths().size(), edges2);
+          _shape1.paths().size(), edges1,
+          _shape2.paths().size(), edges2);
     );
 
     IF_VERBOSE_MALFORMED_SWF(
@@ -310,9 +154,11 @@
         }
 
     );
+#endif
 
 }
 
+} // namespace SWF
 } // namespace gnash
 
 // Local Variables:

=== renamed file 'libcore/parser/morph2_character_def.h' => 
'libcore/swf/DefineMorphShapeTag.h'
--- a/libcore/parser/morph2_character_def.h     2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineMorphShapeTag.h 2009-04-07 12:34:43 +0000
@@ -1,27 +1,73 @@
-// morph2.h -- Mike Shaver <address@hidden> 2003, , Vitalij Alexeev 
<address@hidden> 2004.
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-#ifndef GNASH_MORPH2_H
-#define GNASH_MORPH2_H
+// DefineMorphShapeTag.h:   Load and parse morphing shapes, for Gnash.
+//
+//   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Based on the public domain work of Mike Shaver <address@hidden> 2003,
+// Vitalij Alexeev <address@hidden> 2004.
+
+#ifndef GNASH_SWF_MORPH_SHAPE_H
+#define GNASH_SWF_MORPH_SHAPE_H
 
 #include "smart_ptr.h" // GNASH_USE_GC
-#include "shape_character_def.h" // for inheritance of morph2_character_def
 #include "swf.h"
-
-namespace gnash {
-
-class SWFStream;
+#include "ShapeRecord.h"
+#include "DefinitionTag.h"
+
+// Forward declarations.
+namespace gnash {
+    class movie_definition;
+    class SWFStream;
+    class MorphShape;
+}
+
+namespace gnash {
+namespace SWF {
 
 /// DefineMorphShape tag
 //
-class morph2_character_def : public shape_character_def
+class DefineMorphShapeTag : public DefinitionTag
 {
 public:
-    morph2_character_def();
-    virtual ~morph2_character_def();
-
+
+    static void loader(SWFStream& in, TagType tag, movie_definition& m,
+            const RunInfo& r);
+
+    virtual ~DefineMorphShapeTag() {}
+
+       virtual DisplayObject* createDisplayObject(DisplayObject* parent, int 
id);
+
+    virtual void display(const MorphShape& inst) const;
+
+    const ShapeRecord& shape1() const { 
+        return _shape1;
+    }
+    
+    const ShapeRecord& shape2() const { 
+        return _shape2;
+    }
+
+    virtual const rect& get_bound() const {
+        return _bounds;
+    }
+
+private:
+
+    DefineMorphShapeTag(SWFStream& in, SWF::TagType tag, movie_definition& md);
+    
     /// Read a DefineMorphShape tag from stream
     //
     /// Throw ParserException if the tag is malformed
@@ -41,41 +87,18 @@
     ///
     void read(SWFStream& in, SWF::TagType tag, movie_definition& m);
 
-    virtual void display(DisplayObject* inst);
-
-    // Question: What is the bound of a morph? Is this conceptually correct?
-    /// TODO: optimize this by take ratio into consideration, to decrease some
-    /// invalidated area when rendering morphs
-    virtual const rect&        get_bound() const 
-    { 
-        _bound.expand_to_rect(m_shape1->get_bound());
-        _bound.expand_to_rect(m_shape2->get_bound());
-        return _bound;
-    }
-
-protected:
-
-#ifdef GNASH_USE_GC
-    /// Reachable resources are:
-    ///        - The start and end shapes (m_shape1, m_shape2)
-    virtual void markReachableResources() const
-    {
-        if (m_shape1) m_shape1->setReachable();
-        if (m_shape2) m_shape2->setReachable();
-    }
-#endif 
-
-private:
-    boost::intrusive_ptr<shape_character_def> m_shape1;
-    boost::intrusive_ptr<shape_character_def> m_shape2;
-    
-    mutable rect _bound;
-    
+    ShapeRecord _shape1;
+    ShapeRecord _shape2;
+    
+    rect _bounds;
+
 };
+
+} // namespace SWF
 } // namespace gnash
 
 
-#endif // GNASH_MORPH2_H
+#endif 
 
 // Local Variables:
 // mode: C++

=== renamed file 'libcore/parser/shape_character_def.cpp' => 
'libcore/swf/DefineShapeTag.cpp'
--- a/libcore/parser/shape_character_def.cpp    2009-04-03 09:48:13 +0000
+++ b/libcore/swf/DefineShapeTag.cpp    2009-04-07 13:07:42 +0000
@@ -1,4 +1,4 @@
-// shape_character_def.cpp:  Quadratic bezier outline shapes, for Gnash.
+// DefineShapeTag.cpp:  Quadratic bezier outline shapes, for Gnash.
 //
 //   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 //
@@ -23,7 +23,7 @@
 // Quadratic bezier outline shapes are the basis for most SWF rendering.
 
 
-#include "shape_character_def.h"
+#include "DefineShapeTag.h"
 #include "smart_ptr.h" // GNASH_USE_GC
 #include "impl.h"
 #include "log.h"
@@ -31,6 +31,7 @@
 #include "Shape.h"
 #include "SWFStream.h"
 #include "MovieClip.h"
+#include "swf.h"
 
 #include <algorithm>
 
@@ -38,844 +39,64 @@
 // and compare them with the bounds encoded in the SWF
 //#define GNASH_DEBUG_SHAPE_BOUNDS 1
 
-namespace gnash
+namespace gnash {
+namespace SWF {
+
+void
+DefineShapeTag::loader(SWFStream& in, TagType tag, movie_definition& m,
+        const RunInfo& /*r*/)
 {
+    assert(tag == DEFINESHAPE ||
+           tag == DEFINESHAPE2 ||
+           tag == DEFINESHAPE3 ||
+           tag == DEFINESHAPE4 ||
+           tag == DEFINESHAPE4_);
+
+    in.ensureBytes(2);
+    boost::uint16_t id = in.read_u16();
+    IF_VERBOSE_PARSE(
+        log_parse(_("DefineShapeTag(%s): id = %d"), tag, id);
+    );
+
+    DefineShapeTag* ch = new DefineShapeTag(in, tag, m);
+    m.addDisplayObject(id, ch);
+
+}
 
 DisplayObject*
-shape_character_def::createDisplayObject(DisplayObject* parent, int id)
+DefineShapeTag::createDisplayObject(DisplayObject* parent, int id)
 {
        return new Shape(this, parent, id);
 }
-
-// Read fill styles, and push them onto the given style array.
-static void
-read_fill_styles(std::vector<fill_style>& styles, SWFStream& in,
-                 SWF::TagType tag, movie_definition& m)
-{
-    in.ensureBytes(1);
-    boost::uint16_t  fill_style_count = in.read_u8();
-    if (tag > 2)
-    {
-        if (fill_style_count == 0xFF)
-        {
-            in.ensureBytes(2);
-            fill_style_count = in.read_u16();
-        }
-    }
-
-    IF_VERBOSE_PARSE (
-        log_parse(_("  read_fill_styles: count = %u"), fill_style_count);
-    );
-
-    // Read the styles.
-    styles.reserve(styles.size()+fill_style_count);
-    for (boost::uint16_t i = 0; i < fill_style_count; ++i)
-    {
-        // TODO: add a fill_style constructor directly reading from stream
-        fill_style fs;
-        fs.read(in, tag, m);
-        styles.push_back(fs);
-    }
-}
-
-// Read line styles and push them onto the back of the given array.
-static void
-read_line_styles(std::vector<line_style>& styles, SWFStream& in, SWF::TagType 
tag,
-                 movie_definition& md)
-{
-    in.ensureBytes(1);
-    int line_style_count = in.read_u8();
-
-    IF_VERBOSE_PARSE(
-        log_parse(_("  read_line_styles: count = %d"), line_style_count);
-    );
-
-    if (line_style_count == 0xFF)
-    {
-        in.ensureBytes(2);
-        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.back().read(in, tag, md);
-    }
-}
-
-shape_character_def::shape_character_def()
-    :
-    character_def(),
-    _fill_styles(),
-    _line_styles(),
-    _paths(),
-    _bound()
-{  }
-
-shape_character_def::shape_character_def(const shape_character_def& o)
-    :
-    character_def(o),
-    _fill_styles(o._fill_styles),
-    _line_styles(o._line_styles),
-    _paths(o._paths),
-    _bound(o._bound)
-    {
-    }
-
-shape_character_def::~shape_character_def()
-{
-}
-
-void
-shape_character_def::read(SWFStream& in, SWF::TagType tag, bool with_style,
-                          movie_definition& m)
-{
-    if (with_style)
-    {
-        _bound.read(in);
-    
-        IF_VERBOSE_PARSE(
-            std::string b = _bound.toString();
-            log_parse(_("  bound rect: %s"), b.c_str());
-        );
-    
-        // TODO: Store and use these. Unfinished.
-        if (tag == SWF::DEFINESHAPE4 || tag == SWF::DEFINESHAPE4_)
-        {
-            rect tbound;
-            tbound.read(in);
-            in.ensureBytes(1);
-            static_cast<void>(in.read_u8());
-            LOG_ONCE(log_unimpl("DEFINESHAPE4 edge boundaries and scales"));
-        }
-    
-        read_fill_styles(_fill_styles, in, tag, m);
-        read_line_styles(_line_styles, in, tag, m);
-    }
-
-    /// Adding a dummy fill style is just needed to make the
-    /// parser somewhat more robust. This fill style is not
-    /// really used, as text rendering will use style information
-    /// from TEXTRECORD tag instead.
-    ///
-    if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2 )
-    {
-        assert(!with_style);
-    }
-    
-    // Use read_u8 to force alignment.
-    in.ensureBytes(1);
-    boost::uint8_t num_bits = in.read_u8();
-    int num_fill_bits = (num_bits & 0xF0) >> 4;
-    int num_line_bits = (num_bits & 0x0F);
-    
-    IF_VERBOSE_PARSE(
-        log_parse(_("  shape_character_def read: nfillbits = %d, "
-                "nlinebits = %d"), num_fill_bits, num_line_bits);
-    );
-    
-    if ( !num_fill_bits && !num_line_bits )
-    {
-        /// When reading font glyphs it happens to read 1 byte
-        /// past end boundary of a glyph due to fill/line bits being
-        /// zero.
-        ///
-        /// Generally returning here seems to break morphs:
-        ///  http://savannah.gnu.org/bugs/?21747
-        /// And other normal shapes:
-        ///  http://savannah.gnu.org/bugs/?21923
-        ///  http://savannah.gnu.org/bugs/?22000
-        ///
-        /// So for now we only return if NOT reading a morph shape.
-        /// Pretty ugly... till next bug report.
-        ///
-        ///
-        if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2 || 
-                tag == SWF::DEFINEFONT3)
-        {
-            log_debug("Skipping glyph read, being fill and line bits zero. "
-                    "SWF tag is %d.", tag);
-            return;
-        }
-    }
-    
-    // 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;
-    int   x = 0, y = 0;
-    path  current_path;
-
-#define SHAPE_LOG 0
-    
-    // SHAPERECORDS
-    for (;;)
-    {
-        in.ensureBits(1);
-        bool isEdgeRecord = in.read_bit();
-        if (!isEdgeRecord)
-        {
-            // Parse the record.
-            in.ensureBits(5);
-            int flags = in.read_uint(5);
-            if (flags == flagEnd)
-            {  
-                // Store the current path if any.
-                if (! current_path.is_empty())
-                {
-                    _paths.push_back(current_path);
-                    current_path.m_edges.resize(0);
-                }
-                break;
-            }
-            if (flags & flagMove)
-            {  
-                // Store the current path if any, and prepare a fresh one.
-                if (! current_path.is_empty())
-                {
-                    _paths.push_back(current_path);
-                    current_path.m_edges.resize(0);
-                }
-                in.ensureBits(5);
-                int num_move_bits = in.read_uint(5);
-                in.ensureBits(2 * num_move_bits);
-                int move_x = in.read_sint(num_move_bits);
-                int move_y = in.read_sint(num_move_bits);
-    
-                x = move_x;
-                y = move_y;
-    
-                // Set the beginning of the path.
-                current_path.ap.x = x;
-                current_path.ap.y = y;
-    
-#if SHAPE_LOG
-                IF_VERBOSE_PARSE(
-                    log_parse(_("  Shape read: moveto %d %d"), x, y);
-                );
-#endif
-            }
-            if ((flags & flagFillStyle0Change) && num_fill_bits > 0)
-            {
-                // fill_style_0_change = 1;
-                if (! current_path.is_empty())
-                {
-                    _paths.push_back(current_path);
-                    current_path.m_edges.resize(0);
-                    current_path.ap.x = x;
-                    current_path.ap.y = y;
-                }
-                in.ensureBits(num_fill_bits);
-                unsigned style = in.read_uint(num_fill_bits);
-                if (style > 0)
-                {
-                    style += fill_base;
-                }
-    
-                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
-                {
-                    if ( style > 1 )          // 0:hide 1:renderer
-                    {
-                        IF_VERBOSE_MALFORMED_SWF(
-                             log_swferror(_("Invalid fill style %d in "
-                                     "fillStyle0Change record for font tag "
-                                     "(0 or 1 valid). Set to 0."), style);
-                        );
-                        style = 0;
-                    }
-                }
-                else
-                {
-                    // 1-based index
-                    if ( style > _fill_styles.size() )
-                    {
-                        IF_VERBOSE_MALFORMED_SWF(
-                             log_swferror(_("Invalid fill style %d in "
-                                     "fillStyle0Change record - %d defined. "
-                                     "Set to 0."), style, _fill_styles.size());
-                        );
-                        style = 0;
-                    }
-                }
-    
-                current_path.setLeftFill(style);
-#if SHAPE_LOG
-                IF_VERBOSE_PARSE(
-                     log_parse(_("  Shape read: fill0 (left) = %d"),
-                         current_path.getLeftFill());
-                );
-#endif
-            }
-            if ((flags & flagFillStyle1Change) && num_fill_bits > 0)
-            {
-                // fill_style_1_change = 1;
-                if (! current_path.is_empty())
-                {
-                    _paths.push_back(current_path);
-                    current_path.m_edges.resize(0);
-                    current_path.ap.x = x;
-                    current_path.ap.y = y;
-                }
-                in.ensureBits(num_fill_bits);
-                unsigned style = in.read_uint(num_fill_bits);
-                if (style > 0)
-                {
-                    style += fill_base;
-                }
-    
-                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
-                {
-                    if ( style > 1 )          // 0:hide 1:renderer
-                    {
-                        IF_VERBOSE_MALFORMED_SWF(
-                             log_swferror(_("Invalid fill style %d in "
-                                     "fillStyle1Change record for font tag "
-                                     "(0 or 1 valid). Set to 0."), style);
-                        );
-                        style = 0;
-                    }
-                }
-                else
-                {
-                    // 1-based index
-                    if ( style > _fill_styles.size() )
-                    {
-                        IF_VERBOSE_MALFORMED_SWF(
-                            log_swferror(_("Invalid fill style %d in "
-                                    "fillStyle1Change record - %d defined. "
-                                    "Set to 0."), style, _fill_styles.size());
-                        );
-                        style = 0;
-                    }
-                }
-                current_path.setRightFill(style);
-#if SHAPE_LOG
-                IF_VERBOSE_PARSE (
-                    log_parse(_("  Shape read: fill1 (right) = %d"),
-                        current_path.getRightFill());
-                );
-#endif
-            }
-            if ((flags & flagLineStyleChange) && num_line_bits > 0)
-            {
-                // line_style_change = 1;
-                if (! current_path.is_empty())
-                {
-                    _paths.push_back(current_path);
-                    current_path.m_edges.resize(0);
-                    current_path.ap.x = x;
-                    current_path.ap.y = y;
-                }
-                in.ensureBits(num_line_bits);
-                unsigned style = in.read_uint(num_line_bits);
-                if (style > 0)
-                {
-                    style += line_base;
-                }
-                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
-                {
-                    if ( style > 1 )          // 0:hide 1:renderer
-                    {
-                        IF_VERBOSE_MALFORMED_SWF(
-                            log_swferror(_("Invalid line style %d in "
-                                    "lineStyleChange record for font tag "
-                                    "(0 or 1 valid). Set to 0."), style);
-                        );
-                        style = 0;
-                    }
-                }
-                else {
-                    // 1-based index
-                    if (style > _line_styles.size()) {
-                        IF_VERBOSE_MALFORMED_SWF(
-                            log_swferror(_("Invalid fill style %d in "
-                                    "lineStyleChange record - %d defined. "
-                                    "Set to 0."), style, _line_styles.size());
-                        );
-                        style = 0;
-                    }
-                }
-                current_path.setLineStyle(style);
-#if SHAPE_LOG
-                IF_VERBOSE_PARSE(
-                    log_parse(_("  Shape_read: line = %d"), 
-                        current_path.getLineStyle());
-                )
-#endif
-            }
-            if (flags & flagHasNewStyles)
-            {
-                if (!with_style)
-                {
-                    IF_VERBOSE_MALFORMED_SWF(
-                         log_swferror("Unexpected HasNewStyle flag in tag "
-                             "%d shape record", tag);
-                    );
-                    continue;
-                }
-                IF_VERBOSE_PARSE (
-                    log_parse(_("  Shape read: more fill styles"));
-                );
-    
-                // Store the current path if any.
-                if (! current_path.is_empty())
-                {
-                    _paths.push_back(current_path);
-                    current_path.clear();
-                }
-    
-                // 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?
-                _paths.push_back(path());
-                _paths.back().m_new_shape = true;
-    
-                fill_base = _fill_styles.size();
-                line_base = _line_styles.size();
-                read_fill_styles(_fill_styles, in, tag, m);
-                read_line_styles(_line_styles, in, tag, m);
-    
-                in.ensureBits(8);
-                num_fill_bits = in.read_uint(4);
-                num_line_bits = in.read_uint(4);
-            }
-        }
-        else
-        {
-            // EDGERECORD
-            in.ensureBits(1);
-            bool edge_flag = in.read_bit();
-            if (edge_flag == 0)
-            {
-                in.ensureBits(4);
-                int num_bits = 2 + in.read_uint(4);
-                // curved edge
-                in.ensureBits(4 * num_bits);
-                int cx = x + in.read_sint(num_bits);
-                int cy = y + in.read_sint(num_bits);
-                int ax = cx + in.read_sint(num_bits);
-                int ay = cy + in.read_sint(num_bits);
-    
-#if SHAPE_LOG
-                IF_VERBOSE_PARSE (
-                    log_parse(_("  Shape read: curved edge   = "
-                            "%d %d - %d %d - %d %d"), x, y, cx, cy, ax, ay);
-                );
-#endif
-                current_path.m_edges.push_back(edge(cx, cy, ax, ay));
-                x = ax;
-                y = ay;
-            }
-            else
-            {
-                // straight edge
-                in.ensureBits(5);
-                int num_bits = 2 + in.read_uint(4);
-                bool  line_flag = in.read_bit();
-                int dx = 0, dy = 0;
-                if (line_flag)
-                {
-                    // General line.
-                    in.ensureBits(2 * num_bits);
-                    dx = in.read_sint(num_bits);
-                    dy = in.read_sint(num_bits);
-                }
-                else
-                {
-                    in.ensureBits(1);
-                    bool vert_flag = in.read_bit();
-                    if (vert_flag == 0)
-                    {
-                        // Horizontal line.
-                        in.ensureBits(num_bits);
-                        dx = in.read_sint(num_bits);
-                    }
-                    else
-                    {
-                        // Vertical line.
-                        in.ensureBits(num_bits);
-                        dy = in.read_sint(num_bits);
-                    }
-                }
-    
-#if SHAPE_LOG
-                IF_VERBOSE_PARSE (
-                     log_parse(_("  Shape_read: straight edge = "
-                             "%d %d - %d %d"), x, y, x + dx, y + dy);
-                );
-#endif
-                current_path.m_edges.push_back(edge(x + dx, y + dy,
-                            x + dx, y + dy));
-                x += dx;
-                y += dy;
-            }
-        }
-    }
-    
-    if ( ! with_style )
-    {
-        // TODO: performance would be improved by computing
-        //       the bounds as edges are parsed.
-        compute_bound(_bound, m.get_version());
-    }
-#ifdef GNASH_DEBUG_SHAPE_BOUNDS
-    else
-    {
-        rect computedBounds;
-        compute_bound(computedBounds, m->get_version());
-        if ( computedBounds != m_bounds )
-        {
-            log_debug("Shape DisplayObject read for tag %d contained embedded "
-                    "bounds %s, while we computed bounds %s",
-                    tag, m_bound, computedBounds);
-        }
-    }
-#endif
-}
-
-void
-shape_character_def::display(DisplayObject* inst)
-{
-    // Draw the shape using our own inherent styles.
-    render::drawShape(this, inst);
-}
-
-
-// TODO: this should be moved to libgeometry or something
-// Finds the quadratic bezier curve crossings with the line Y.
-// The function can have zero, one or two solutions (cross1, cross2). The
-// return value of the function is the number of solutions.
-// x0, y0 = start point of the curve
-// x1, y1 = end point of the curve (anchor, aka ax|ay)
-// cx, cy = control point of the curve
-// If there are two crossings, cross1 is the nearest to x0|y0 on the curve.
-int curve_x_crossings(float x0, float y0, float x1, float y1,
-    float cx, float cy, float y, float &cross1, float &cross2)
-{
-    int count=0;
-
-    // check if any crossings possible
-    if ( ((y0 < y) && (y1 < y) && (cy < y))
-        || ((y0 > y) && (y1 > y) && (cy > y)) )
-    {
-        // all above or below -- no possibility of crossing
-        return 0;
-    }
-
-    // Quadratic bezier is:
-    //
-    // p = (1-t)^2 * a0 + 2t(1-t) * c + t^2 * a1
-    //
-    // We need to solve for x at y.
-
-    // Use the quadratic formula.
-
-    // Numerical Recipes suggests this variation:
-    // q = -0.5 [b +sgn(b) sqrt(b^2 - 4ac)]
-    // x1 = q/a;  x2 = c/q;
-
-    float A = y1 + y0 - 2 * cy;
-    float B = 2 * (cy - y0);
-    float C = y0 - y;
-
-    float rad = B * B - 4 * A * C;
-
-    if (rad < 0)
-    {
-        return 0;
-    }
-    else
-    {
-        float q;
-        float sqrt_rad = sqrtf(rad);
-        if (B < 0)
-        {
-            q = -0.5f * (B - sqrt_rad);
-        }
-        else
-        {
-            q = -0.5f * (B + sqrt_rad);
-        }
-
-        // The old-school way.
-        // float t0 = (-B + sqrt_rad) / (2 * A);
-        // float t1 = (-B - sqrt_rad) / (2 * A);
-
-        if (q != 0)
-        {
-            float t1 = C / q;
-            if (t1 >= 0 && t1 < 1)
-            {
-                float x_at_t1 =
-                    x0 + 2 * (cx - x0) * t1 + (x1 + x0 - 2 * cx) * t1 * t1;
-
-                count++;
-                assert(count==1);
-                cross1 = x_at_t1;             // order is important!
-            }
-        }
-
-        if (A != 0)
-        {
-            float t0 = q / A;
-            if (t0 >= 0 && t0 < 1)
-            {
-                float x_at_t0 =
-                    x0 + 2 * (cx - x0) * t0 + (x1 + x0 - 2 * cx) * t0 * t0;
-
-                count++;
-                // order is important!
-                if (count == 2) cross2 = x_at_t0;
-                else cross1 = x_at_t0;
-            }
-        }
-
-    }
-
-    return count;
-}
-
-bool  shape_character_def::point_test_local(boost::int32_t x,
-        boost::int32_t y, const SWFMatrix& wm)
-{
-    /*
-    Principle:
-    For the fill of the shape, we project a ray from the test point to the left
-    side of the shape counting all crossings. When a line or curve segment is
-    crossed we add 1 if the left fill style is set. Regardless of the left fill
-    style we subtract 1 from the counter then the right fill style is set.
-    This is true when the line goes in downward direction. If it goes upward,
-    the fill styles are reversed.
-
-    The final counter value reveals if the point is inside the shape (and
-    depends on filling rule, see below).
-    This method should not depend on subshapes and work for some malformed
-    shapes situations:
-    - wrong fill side (eg. left side set for a clockwise drawen rectangle)
-    - intersecting paths
-    */
-    point pt(x, y);
-
-    // later we will need non-zero for glyphs... (TODO)
-    bool even_odd = true;  
-
-    // FIXME: if the shape contains non-scaled strokes
-    //        we can't rely on boundary itself for a quick
-    //        way out. Bounds supposedly already include
-    //        thickness, so we might keep a flag telling us
-    //        whether *non_scaled* strokes are present
-    //        and if not still use the boundary check.
-    // NOTE: just skipping this test breaks a corner-case
-    //       in DrawingApiTest (kind of a fill-leakage making
-    //       the collision detection find you inside a self-crossing
-    //       shape).
-    //
-    if (_bound.point_test(x, y) == false)
-    {
-        return false;
-    }
-
-    unsigned npaths = _paths.size();
-    int counter = 0;
-
-    // browse all paths
-    for (unsigned pno=0; pno<npaths; pno++)
-    {
-        const path& pth = _paths[pno];
-        unsigned nedges = pth.m_edges.size();
-
-        float next_pen_x = pth.ap.x;
-        float next_pen_y = pth.ap.y;
-        float pen_x, pen_y;
-
-        if (pth.m_new_shape)
-        {
-            if ( ( even_odd && (counter % 2) != 0) ||
-                 (!even_odd && (counter != 0)) )
-            {
-                // the point is inside the previous subshape, so exit now
-                return true;
-            }
-
-            counter=0;
-        }
-        if (pth.empty()) continue;
-
-        // If the path has a line style, check for strokes there
-        if (pth.m_line != 0 )
-        {
-            assert(_line_styles.size() >= pth.m_line);
-            line_style& ls = _line_styles[pth.m_line-1];
-            double thickness = ls.getThickness();
-            if (! thickness )
-            {
-                thickness = 20; // at least ONE PIXEL thick.
-            }
-            else if ((!ls.scaleThicknessVertically()) &&
-                    (!ls.scaleThicknessHorizontally()) )
-            {
-                // TODO: pass the SWFMatrix to withinSquareDistance instead ?
-                double xScale = wm.get_x_scale();
-                double yScale = wm.get_y_scale();
-        //log_debug("thickness:%d, xScale:%g, yScale:%g", thickness, xScale, 
yScale);
-                thickness *= std::max(xScale, yScale);
-        //log_debug("after scaling, thickness:%d", thickness);
-            }
-            else if (ls.scaleThicknessVertically() != 
-                    ls.scaleThicknessHorizontally())
-            {
-                LOG_ONCE( log_unimpl("Collision detection for "
-                            "unidirectionally scaled strokes") );
-            }
-
-            double dist = thickness / 2.0;
-            double sqdist = dist * dist;
-            if (pth.withinSquareDistance(pt, sqdist))
-                return true;
-        }
-
-        // browse all edges of the path
-        for (unsigned eno=0; eno<nedges; eno++)
-        {
-            const edge& edg = pth.m_edges[eno];
-            pen_x = next_pen_x;
-            pen_y = next_pen_y;
-            next_pen_x = edg.ap.x;
-            next_pen_y = edg.ap.y;
-
-            float cross1, cross2;
-            int dir1, dir2 = 0; // +1 = downward, -1 = upward
-            int crosscount = 0;
-
-            if (edg.is_straight())
-            {
-                // ignore horizontal lines
-                // TODO: better check for small difference?
-                if (edg.ap.y == pen_y)  
-                {
-                    continue;
-                }
-                // does this line cross the Y coordinate?
-                if ( ((pen_y <= y) && (edg.ap.y >= y))
-                    || ((pen_y >= y) && (edg.ap.y <= y)) )
-                {
-
-                    // calculate X crossing
-                    cross1 = pen_x + (edg.ap.x - pen_x) *
-                        (y - pen_y) / (edg.ap.y - pen_y);
-
-                    if (pen_y > edg.ap.y)
-                        dir1 = -1;  // upward
-                    else
-                        dir1 = +1;  // downward
-
-                    crosscount = 1;
-                }
-                else
-                {
-                    // no crossing found
-                    crosscount = 0;
-                }
-            }
-            else
-            {
-                // ==> curve case
-                crosscount = curve_x_crossings(pen_x, pen_y, edg.ap.x, 
edg.ap.y,
-                    edg.cp.x, edg.cp.y, y, cross1, cross2);
-                dir1 = pen_y > y ? -1 : +1;
-                dir2 = dir1 * (-1); // second crossing always in opposite dir.
-            } // curve
-
-            // ==> we have now:
-            //  - one (cross1) or two (cross1, cross2) ray crossings (X
-            //    coordinate)
-            //  - dir1/dir2 tells the direction of the crossing
-            //    (+1 = downward, -1 = upward)
-            //  - crosscount tells the number of crossings
-
-            // need at least one crossing
-            if (crosscount == 0)
-            {
-                continue;
-            }
-
-            bool touched = false;
-
-            // check first crossing
-            if (cross1 <= x)
-            {
-                if (pth.m_fill0 > 0) counter += dir1;
-                if (pth.m_fill1 > 0) counter -= dir1;
-
-                touched = true;
-            }
-
-            // check optional second crossing (only possible with curves)
-            if ( (crosscount > 1) && (cross2 <= x) )
-            {
-                if (pth.m_fill0 > 0) counter += dir2;
-                if (pth.m_fill1 > 0) counter -= dir2;
-
-                touched = true;
-            }
-
-        }// for edge
-    } // for path
-
-    return ( (even_odd && (counter % 2) != 0) ||
-             (!even_odd && (counter != 0)) );
-}
-
-// Find the bounds of this shape, and store them in the given rectangle.
-void
-shape_character_def::compute_bound(rect& r, int swfVersion) const
-{
-    r.set_null();
-
-    for (unsigned int i = 0; i < _paths.size(); i++)
-    {
-        const path& p = _paths[i];
-
-        unsigned thickness = 0;
-        if ( p.m_line )
-        {
-            // For glyph shapes m_line is allowed to be 1
-            // while no defined line styles are allowed.
-            if ( _line_styles.empty() )
-            {
-                // This is either a Glyph, for which m_line==1 is valid
-                // or a bug in the parser, which we have no way to
-                // check at this time
-                assert(p.m_line == 1);
-            }
-            else
-            {
-                thickness = _line_styles[p.m_line-1].getThickness();
-            }
-        }
-        p.expandBounds(r, thickness, swfVersion);
-    }
-}
-
-#ifdef GNASH_USE_GC
-void  shape_character_def::markReachableResources() const
-{
-    assert(isReachable());
-    std::for_each(_fill_styles.begin(), _fill_styles.end(),
-            std::mem_fun_ref(&fill_style::markReachableResources));
-}
-#endif
-
-} // end namespace gnash
+    
+bool
+DefineShapeTag::pointTestLocal(boost::int32_t x, boost::int32_t y, 
+     const SWFMatrix& wm) const
+{
+    return geometry::pointTest(_shape.paths(), _shape.lineStyles(), x, y, wm);
+}
+
+
+DefineShapeTag::DefineShapeTag(SWFStream& in, TagType tag,
+        movie_definition& m)
+    :
+    DefinitionTag(),
+    _shape(in, tag, m)
+{
+}
+
+void
+DefineShapeTag::display(const DisplayObject& inst) const
+{
+    render::drawShape(_shape, inst.get_world_cxform(), inst.getWorldMatrix());
+}
+
+void
+DefineShapeTag::markReachableResources() const
+{}
+
+} // namespace SWF
+} // namespace gnash
 
 // Local Variables:
 // mode: C++

=== renamed file 'libcore/parser/shape_character_def.h' => 
'libcore/swf/DefineShapeTag.h'
--- a/libcore/parser/shape_character_def.h      2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineShapeTag.h      2009-04-07 12:45:25 +0000
@@ -9,100 +9,44 @@
 #ifndef GNASH_SHAPE_CHARACTER_DEF_H
 #define GNASH_SHAPE_CHARACTER_DEF_H
 
-#include "character_def.h" // for inheritance of shape_character_def
+#include "DefinitionTag.h" // for inheritance of DefineShapeTag
 #include "smart_ptr.h" // GNASH_USE_GC
-#include "Geometry.h"     // for path
-#include "rect.h"      // for composition
-#include "fill_style.h" // for fill style
-#include "styles.h"     // for line style
 #include "swf.h"
-
-#include <vector> // for composition
-
+#include "ShapeRecord.h"
 
 namespace gnash {
        class SWFStream;
        class cxform;
+    class Shape;
        class SWFMatrix;
 }
 
 namespace gnash {
+namespace SWF {
 
 /// \brief
 /// Represents the outline of one or more shapes, along with
 /// information on fill and line styles.
-//
-class shape_character_def : public character_def
+class DefineShapeTag : public DefinitionTag
 {
 public:
 
-    typedef std::vector<fill_style> FillStyles;
-    typedef std::vector<line_style> LineStyles;
-    typedef std::vector<path> Paths;
-
-    shape_character_def();
-    virtual ~shape_character_def();
-
-    virtual void display(DisplayObject* inst);
-
-    /// Return true if the specified point is on the interior of our shape.
-    //
-    /// Incoming coords are local coords (twips).
-    /// The SWFMatrix will be used for lines with non-scalable strokes.
-    ///
-    virtual bool point_test_local(boost::int32_t x, boost::int32_t y,
-            const SWFMatrix& wm);
-
+    static void loader(SWFStream& in, TagType tag, movie_definition& m,
+            const RunInfo& r);
+
+    virtual ~DefineShapeTag() {};
+
+    // Display a Shape character.
+    virtual void display(const DisplayObject& inst) const;
+
+    // Create a Shape DisplayObject.
        virtual DisplayObject* createDisplayObject(DisplayObject* parent, int 
id);
        
-    /// \brief
-    /// Read a shape definition as included in DEFINEFONT*,
-    /// DEFINESHAPE* or DEFINEMORPH* tag
-    //
-    /// @param in
-    ///        The stream to read the shape from
-    ///
-    /// @param TagType
-    ///        The SWF::TagType this shape definition is read for.
-    ///        TODO: change to an actual SWF::TagType type
-    ///
-    /// @param with_style
-    ///        If true, this definition includes bounds, fill styles and line 
styles.
-    ///        Tipically, this is only false for DEFINEFONT* tags.
-    ///        NOTE: if with_style is false, bounds of the shape will be 
computed
-    ///              rather then read.
-    ///        TODO: drop this function, set based on TagType ?
-    ///
-    /// @param m
-    ///        The movie definition corresponding to the SWF we/re parsing.
-    ///        This is used to resolve bitmap DisplayObjects for fill styles, 
never
-    ///        used if with_style is false.
-    void read(SWFStream& in, SWF::TagType tag, bool with_style,
-            movie_definition& m);
-
     /// Get cached bounds of this shape.
-    const rect&        get_bound() const { return _bound; }
-
-    /// Compute bounds by looking at the component paths
-    void compute_bound(rect& r, int swfVersion) const;
-
-    const FillStyles& fillStyles() const { return _fill_styles; }
-    const LineStyles& lineStyles() const { return _line_styles; }
-
-    const Paths& paths() const { return _paths; }
-
-    // morph uses this
-    // Should this be verified?
-    void set_bound(const rect& r) { _bound = r; }
-
-    // Morph uses this.
-    void addFillStyle(const fill_style& fs) {
-        _fill_styles.push_back(fs);
-    }
-
-    void addLineStyle(const line_style& fs) {
-        _line_styles.push_back(fs);
-    }
+    const rect&        get_bound() const { return _shape.getBounds(); }
+
+    virtual bool pointTestLocal(boost::int32_t x, boost::int32_t y, 
+            const SWFMatrix& wm) const;
 
 protected:
 
@@ -114,38 +58,22 @@
     ///          These are not actual resources, but may contain some.
     ///
     virtual void markReachableResources() const;
-#endif // GNASH_USE_GC
-
-    // derived morph classes changes these
-    FillStyles _fill_styles;
-    LineStyles _line_styles;
-    Paths _paths;
-    rect _bound;
-
-    /// Copy a shape DisplayObject definition
-    shape_character_def(const shape_character_def& o);
+#endif 
 
 private:
 
-    /// Shape record flags
-    enum ShapeRecordFlags {
-        flagEnd = 0x00,
-        flagMove = 0x01,
-        flagFillStyle0Change = 0x02,
-        flagFillStyle1Change = 0x04,
-        flagLineStyleChange = 0x08,
-        flagHasNewStyles = 0x10
-    };
-    
-    // Don't assign to a shape DisplayObject definition
-    shape_character_def& operator= (const shape_character_def&);
+    DefineShapeTag(SWFStream& in, TagType tag, movie_definition& m);
+
+    /// The actual shape data is stored in this record.
+    const ShapeRecord _shape;
 
 };
 
-}      // end namespace gnash
-
-
-#endif // GNASH_SHAPE_CHARACTER_DEF_H
+} // namespace SWF
+} // namespace gnash
+
+
+#endif 
 
 
 // Local Variables:

=== modified file 'libcore/swf/DefineTextTag.cpp'
--- a/libcore/swf/DefineTextTag.cpp     2009-04-03 09:48:13 +0000
+++ b/libcore/swf/DefineTextTag.cpp     2009-04-07 11:14:10 +0000
@@ -1,4 +1,4 @@
-// DefineTextTag.cpp:  Read text DisplayObject definitions, for Gnash.
+// DefineTextTag.cpp:  Read StaticText definitions, for Gnash.
 
 // Derived from text.cpp       -- Thatcher Ulrich <address@hidden> 2003
 
@@ -33,7 +33,7 @@
 
     std::auto_ptr<DefineTextTag> t(new DefineTextTag(in, m, tag));
     IF_VERBOSE_PARSE(
-        log_parse(_("Text DisplayObject, id = %d"), id);
+        log_parse(_("DefineTextTag, id = %d"), id);
     );
 
     m.addDisplayObject(id, t.release());
@@ -45,10 +45,9 @@
     return new StaticText(this, parent, id);
 }
 
-
 bool
 DefineTextTag::extractStaticText(std::vector<const TextRecord*>& to,
-        size_t& numChars)
+        size_t& numChars) const
 {
     if (_textRecords.empty()) return false;
 
@@ -107,7 +106,7 @@
 }
 
 void
-DefineTextTag::display(DisplayObject* inst)
+DefineTextTag::display(const StaticText& inst) const
 {
 
        const bool useEmbeddedGlyphs = true;

=== modified file 'libcore/swf/DefineTextTag.h'
--- a/libcore/swf/DefineTextTag.h       2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineTextTag.h       2009-04-07 12:34:43 +0000
@@ -18,7 +18,7 @@
 #ifndef GNASH_SWF_DEFINETEXTTAG_H
 #define GNASH_SWF_DEFINETEXTTAG_H
 
-#include "character_def.h" // for inheritance
+#include "DefinitionTag.h" // for inheritance
 #include "styles.h" 
 #include "rect.h" // for composition
 #include "swf.h"
@@ -30,18 +30,19 @@
     class movie_definition;
     class SWFStream;
     class RunInfo;
+    class StaticText;
 }
 
 namespace gnash {
 namespace SWF {
 
 
-/// Text DisplayObject 
+/// StaticText DisplayObject 
 //
 /// This is either read from SWF stream 
 /// or (hopefully) created with scripting
 ///
-class DefineTextTag : public character_def
+class DefineTextTag : public DefinitionTag
 {
 public:
 
@@ -49,7 +50,7 @@
             const RunInfo& r);
 
        /// Draw the string.
-       void display(DisplayObject* inst);
+       void display(const StaticText& inst) const;
        
        const rect&     get_bound() const {
         // TODO: There is a _matrix field in the definition(!) that's
@@ -63,7 +64,8 @@
     ///             if any are present
     /// @param size Will contain the number of DisplayObjects in this
     ///             StaticText definition.
-    bool extractStaticText(std::vector<const TextRecord*>& to, size_t& size);
+    bool extractStaticText(std::vector<const TextRecord*>& to, size_t& size)
+        const;
 
     virtual DisplayObject* createDisplayObject(DisplayObject* parent, int id);
 

=== modified file 'libcore/swf/DefineVideoStreamTag.h'
--- a/libcore/swf/DefineVideoStreamTag.h        2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefineVideoStreamTag.h        2009-04-07 12:34:43 +0000
@@ -24,7 +24,7 @@
 #include "gnashconfig.h"
 #endif
 
-#include "character_def.h"
+#include "DefinitionTag.h"
 #include "swf.h"
 #include "rect.h" // for composition
 #include "MediaParser.h" // for videoFrameType and videoCodecType enums
@@ -69,7 +69,7 @@
 
 namespace SWF {
 
-class DefineVideoStreamTag : public character_def
+class DefineVideoStreamTag : public DefinitionTag
 {
 public:
        
@@ -146,7 +146,7 @@
        /// Construct a video stream definition with given ID
        //
        /// NOTE: for dynamically created definitions (ActionScript Video class
-    ///       instances) you can use an id of -1. See character_def
+    ///       instances) you can use an id of -1. See DefinitionTag
     ///       constructor, as that's the one which will eventually get passed
     ///       the id.
     /// NOTE: What dynamically created definitions?

=== renamed file 'libcore/parser/character_def.h' => 
'libcore/swf/DefinitionTag.h'
--- a/libcore/parser/character_def.h    2009-04-03 09:18:40 +0000
+++ b/libcore/swf/DefinitionTag.h       2009-04-07 12:45:25 +0000
@@ -15,13 +15,14 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-#ifndef GNASH_CHARACTER_DEF_H
-#define GNASH_CHARACTER_DEF_H
+#ifndef GNASH_DEFINITION_TAG_H
+#define GNASH_DEFINITION_TAG_H
 
 #include "ExportableResource.h"
 
 #include <boost/cstdint.hpp>
 #include <vector>
+#include <boost/noncopyable.hpp>
 
 // Forward declarations
 
@@ -35,10 +36,7 @@
 }
 
 namespace gnash {
-
-
-class render_cache_manager; 
-
+namespace SWF {
 
 /// Immutable data representing the template of a movie element.
 //
@@ -46,97 +44,26 @@
 /// can be mixed into movie_definition and sprite_definition,
 /// without using multiple inheritance.
 ///
-class character_def : public ExportableResource
+class DefinitionTag : public ExportableResource, boost::noncopyable
 {
 public:
 
-    character_def()
-               :
-               m_render_cache(0),
-               _id(-1)
-    {
-    }
-
-       
-       virtual ~character_def();
-       
-       virtual void display(DisplayObject* /*instance_info*/)
-       {
-       }
-
-       /// Return true if the specified point is on the interior of our shape.
-       //
-       /// Point coordinates are local coords (TWIPS)
-       ///
-       /// @param wm
-       ///     Current world SWFMatrix of the instance we want to check.
-       ///     This is needed to properly scale non-scalable strokes.
-       ///
-       virtual bool point_test_local(boost::int32_t /*x*/, boost::int32_t 
/*y*/,
-            const SWFMatrix& /*wm*/)
-       {
-               return false;
-       }
-
+       virtual ~DefinitionTag() {};
+       
        /// Should stick the result in a boost::intrusive_ptr immediately.
        //
        /// default is to make a DisplayObject
        ///
-       virtual DisplayObject* createDisplayObject(DisplayObject* parent, int 
id) = 0;
+       virtual DisplayObject* createDisplayObject(DisplayObject* parent,
+            int id) = 0;
        
        // Declared as virtual here because DisplayObject needs access to it
        virtual const rect&     get_bound() const = 0;
        
-    /// Cache holder for renderer (contents depend on renderer handler)
-    /// Will be deleted by destructor of the character_def.
-    /// We could store by auto_ptr, but I'm afraid that would mean
-    /// including render_handler.h in this header, which I don't like.
-    /// (REF: PIMPL)
-    ///
-    render_cache_manager* m_render_cache;
-
-protected:
-
-       /// Copy a DisplayObject definition
-       //
-       /// The copy will have a NULL render cache object.
-       /// The only known use of copy constructor is from
-       /// duplicateMovieClip, in particular during copy
-       /// of the drawable object, which is a subclass
-       /// of a shape_character_def
-       ///
-       /// The choice of NOT copying the cache manager
-       /// is a choice of simplicity. We can't copy the
-       /// pointer as the character_def destructor will
-       /// destroy it, and we don't want to destroy it twice.
-       /// We don't want to make a copy of the whole cache
-       /// as it might be a waste of resource, we don't want
-       /// to share ownership as some character_def ended up
-       /// NOT being immutable any more !! :(
-       ///
-       /// By setting the cache to NULL we'll leave reconstruction
-       /// of a cache to the renderers.
-       ///
-       /// TODO: improve by implementing copy on write for the cache ?
-       ///
-       character_def(const character_def& o)
-               :
-        ExportableResource(),
-               m_render_cache(0),
-               _id(o._id)
-       {}
-
-private:
-
-    int        _id;
-               
-       // don't assign-to
-       character_def& operator= (const character_def&);
-       
 };
 
-
-}      // namespace gnash
+} // namespace SWF
+} // namespace gnash
 
 #endif 
 

=== added file 'libcore/swf/ShapeRecord.cpp'
--- a/libcore/swf/ShapeRecord.cpp       1970-01-01 00:00:00 +0000
+++ b/libcore/swf/ShapeRecord.cpp       2009-04-07 14:32:06 +0000
@@ -0,0 +1,723 @@
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+#include "ShapeRecord.h"
+#include "swf.h"
+#include "SWFStream.h"
+#include "movie_definition.h"
+#include "Geometry.h"
+#include "GnashNumeric.h"
+
+#include <vector>
+
+namespace gnash {
+namespace SWF {
+
+// Forward declarations
+namespace {
+    void readFillStyles(ShapeRecord::FillStyles& styles, SWFStream& in,
+        SWF::TagType tag, movie_definition& md);
+    void readLineStyles(ShapeRecord::LineStyles& styles, SWFStream& in,
+        SWF::TagType tag, movie_definition& md);
+    void computeBounds(rect& bounds, const ShapeRecord::Paths& paths,
+        const ShapeRecord::LineStyles& lineStyles, int swfVersion);
+}
+
+// Functors for path and style manipulation.
+namespace {
+
+template<typename T>
+class Lerp
+{
+public:
+    Lerp(typename T::const_iterator style1, typename T::const_iterator style2,
+            const double ratio)
+        :
+        _style1(style1),
+        _style2(style2),
+        _ratio(ratio)
+    {}
+
+    void operator()(typename T::value_type& st)
+    {
+        st.set_lerp(*_style1, *_style2, _ratio);
+        ++_style1, ++_style2;
+    }
+
+private:
+    typename T::const_iterator _style1;
+    typename T::const_iterator _style2;
+    const double _ratio;
+};
+
+// Facilities for working with list of paths.
+class PathList
+{
+    typedef SWF::ShapeRecord::Paths Paths;
+public:
+
+    PathList(const Paths& paths)
+        :
+        _paths(paths),
+        _currpath(0),
+        _curredge(0),
+        _nedges(computeNumberOfEdges(_paths))
+    {}
+
+    /// Return number of edges in the path list
+    size_t size() const
+    {
+        return _nedges;
+    }
+
+    /// Get next edge in the path list.
+    //
+    /// After last edge in the list has been fetched,
+    /// next call to this function will return first
+    /// edge again.
+    ///
+    const Edge& getNextEdge()
+    {
+        const Edge& ret = _paths[_currpath][_curredge];
+        if ( ++_curredge >= _paths[_currpath].size() )
+        {
+            if ( ++_currpath >= _paths.size() )
+            {
+                // this is not really needed,
+                // but it's simpler to do so that
+                // to make next call fail or abort..
+                _currpath = 0;
+                _curredge = 0;
+            }
+        }
+        return ret;
+    }
+
+    /// Compute total number of edges
+    static size_t computeNumberOfEdges(const Paths& paths)
+    {
+        size_t count=0;
+        for (Paths::const_iterator i = paths.begin(), e = paths.end();
+                i != e; ++i) {
+
+            count += i->size();
+        }
+        return count;
+    }
+
+private:
+
+    const Paths& _paths;
+
+    size_t _currpath;
+
+    size_t _curredge;
+
+    size_t _nedges;
+
+};
+
+} // anonymous namespace
+
+
+ShapeRecord::ShapeRecord(SWFStream& in, SWF::TagType tag, movie_definition& m)
+{
+    read(in, tag, m);
+}
+
+void
+ShapeRecord::setLerp(const ShapeRecord& a, const ShapeRecord& b,
+        const double ratio)
+{
+
+    // Update current bounds.
+    _bounds.set_lerp(a.getBounds(), b.getBounds(), ratio);
+
+    // fill styles
+    const FillStyles::const_iterator fs1 = a.fillStyles().begin();
+    const FillStyles::const_iterator fs2 = b.fillStyles().begin();
+
+    std::for_each(_fillStyles.begin(), _fillStyles.end(),
+            Lerp<FillStyles>(fs1, fs2, ratio));
+
+    // line styles
+    const LineStyles::const_iterator ls1 = a.lineStyles().begin();
+    const LineStyles::const_iterator ls2 = b.lineStyles().begin();
+
+    std::for_each(_lineStyles.begin(), _lineStyles.end(),
+            Lerp<LineStyles>(ls1, ls2, ratio));
+
+    // This is used for cases in which number
+    // of paths in start shape and end shape are not
+    // the same.
+    const Path empty_path;
+    const Edge empty_edge;
+
+    // shape
+    const Paths& paths1 = a.paths();
+    const Paths& paths2 = b.paths();
+    for (size_t i = 0, k = 0, n = 0; i < _paths.size(); i++)
+    {
+        Path& p = _paths[i];
+        const Path& p1 = i < paths1.size() ? paths1[i] : empty_path;
+        const Path& p2 = n < paths2.size() ? paths2[n] : empty_path;
+
+        const float new_ax = flerp(p1.ap.x, p2.ap.x, ratio);
+        const float new_ay = flerp(p1.ap.y, p2.ap.y, ratio);
+
+        p.reset(new_ax, new_ay, p1.getLeftFill(),
+                p2.getRightFill(), p1.getLineStyle());
+
+        //  edges;
+        const size_t len = p1.size();
+        p.m_edges.resize(len);
+
+        for (size_t j=0; j < p.size(); j++)
+        {
+            Edge& e = p[j];
+            const Edge& e1 = j < p1.size() ? p1[j] : empty_edge;
+
+            const Edge& e2 = k < p2.size() ? p2[k] : empty_edge;
+
+            e.cp.x = static_cast<int>(flerp(e1.cp.x, e2.cp.x, ratio));
+            e.cp.y = static_cast<int>(flerp(e1.cp.y, e2.cp.y, ratio));
+            e.ap.x = static_cast<int>(flerp(e1.ap.x, e2.ap.x, ratio));
+            e.ap.y = static_cast<int>(flerp(e1.ap.y, e2.ap.y, ratio));
+            ++k;
+
+            if (p2.size() <= k) {
+                k = 0;
+                ++n;
+            }
+        }
+    }
+
+}
+
+void
+ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m)
+{
+
+    /// TODO: is this correct?
+    const bool styleInfo = (tag == SWF::DEFINESHAPE ||
+                            tag == SWF::DEFINESHAPE2 ||
+                            tag == SWF::DEFINESHAPE3 ||
+                            tag == SWF::DEFINESHAPE4 ||
+                            tag == SWF::DEFINESHAPE4_);
+
+    if (styleInfo)
+    {
+        _bounds.read(in);
+    
+        IF_VERBOSE_PARSE(
+            std::string b = _bounds.toString();
+            log_parse(_("  bound rect: %s"), b);
+        );
+    
+        // TODO: Store and use these. Unfinished.
+        if (tag == SWF::DEFINESHAPE4 || tag == SWF::DEFINESHAPE4_)
+        {
+            rect tbound;
+            tbound.read(in);
+            in.ensureBytes(1);
+            static_cast<void>(in.read_u8());
+            LOG_ONCE(log_unimpl("DEFINESHAPE4 edge boundaries and scales"));
+        }
+    
+        readFillStyles(_fillStyles, in, tag, m);
+        readLineStyles(_lineStyles, in, tag, m);
+    }
+
+    if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2 )
+    {
+        assert(!styleInfo);
+    }
+    
+    // Use read_u8 to force alignment.
+    in.ensureBytes(1);
+    boost::uint8_t num_bits = in.read_u8();
+    int num_fill_bits = (num_bits & 0xF0) >> 4;
+    int num_line_bits = (num_bits & 0x0F);
+    
+    IF_VERBOSE_PARSE(
+        log_parse(_("  ShapeRecord(%s): fillbits = %d, nlinebits = %d"),
+            tag, num_fill_bits, num_line_bits);
+    );
+    
+    if ( !num_fill_bits && !num_line_bits )
+    {
+        /// When reading font glyphs it happens to read 1 byte
+        /// past end boundary of a glyph due to fill/line bits being
+        /// zero.
+        ///
+        /// Generally returning here seems to break morphs:
+        ///  http://savannah.gnu.org/bugs/?21747
+        /// And other normal shapes:
+        ///  http://savannah.gnu.org/bugs/?21923
+        ///  http://savannah.gnu.org/bugs/?22000
+        ///
+        /// So for now we only return if NOT reading a morph shape.
+        /// Pretty ugly... till next bug report.
+        ///
+        ///
+        if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2 || 
+                tag == SWF::DEFINEFONT3)
+        {
+            log_debug("Skipping glyph read, being fill and line bits zero. "
+                    "SWF tag is %d.", tag);
+            return;
+        }
+    }
+    
+    // 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;
+    int   x = 0, y = 0;
+    Path  current_path;
+
+#define SHAPE_LOG 0
+    
+    // SHAPERECORDS
+    for (;;)
+    {
+        in.ensureBits(1);
+        bool isEdgeRecord = in.read_bit();
+        if (!isEdgeRecord)
+        {
+            // Parse the record.
+            in.ensureBits(5);
+            int flags = in.read_uint(5);
+            if (flags == SHAPE_END)
+            {  
+                // Store the current path if any.
+                if (! current_path.empty())
+                {
+                    _paths.push_back(current_path);
+                    current_path.m_edges.resize(0);
+                }
+                break;
+            }
+            if (flags & SHAPE_MOVE)
+            {  
+                // Store the current path if any, and prepare a fresh one.
+                if (! current_path.empty())
+                {
+                    _paths.push_back(current_path);
+                    current_path.m_edges.resize(0);
+                }
+                in.ensureBits(5);
+                int num_move_bits = in.read_uint(5);
+                in.ensureBits(2 * num_move_bits);
+                int move_x = in.read_sint(num_move_bits);
+                int move_y = in.read_sint(num_move_bits);
+    
+                x = move_x;
+                y = move_y;
+    
+                // Set the beginning of the path.
+                current_path.ap.x = x;
+                current_path.ap.y = y;
+    
+#if SHAPE_LOG
+                IF_VERBOSE_PARSE(
+                    log_parse(_("  Shape read: moveto %d %d"), x, y);
+                );
+#endif
+            }
+            if ((flags & SHAPE_FILLSTYLE0_CHANGE) && num_fill_bits > 0)
+            {
+                // fill_style_0_change = 1;
+                if (! current_path.empty())
+                {
+                    _paths.push_back(current_path);
+                    current_path.m_edges.resize(0);
+                    current_path.ap.x = x;
+                    current_path.ap.y = y;
+                }
+                in.ensureBits(num_fill_bits);
+                unsigned style = in.read_uint(num_fill_bits);
+                if (style > 0)
+                {
+                    style += fill_base;
+                }
+    
+                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
+                {
+                    if ( style > 1 )          // 0:hide 1:renderer
+                    {
+                        IF_VERBOSE_MALFORMED_SWF(
+                             log_swferror(_("Invalid fill style %d in "
+                                     "fillStyle0Change record for font tag "
+                                     "(0 or 1 valid). Set to 0."), style);
+                        );
+                        style = 0;
+                    }
+                }
+                else
+                {
+                    // 1-based index
+                    if ( style > _fillStyles.size() )
+                    {
+                        IF_VERBOSE_MALFORMED_SWF(
+                             log_swferror(_("Invalid fill style %d in "
+                                     "fillStyle0Change record - %d defined. "
+                                     "Set to 0."), style, _fillStyles.size());
+                        );
+                        style = 0;
+                    }
+                }
+    
+                current_path.setLeftFill(style);
+#if SHAPE_LOG
+                IF_VERBOSE_PARSE(
+                     log_parse(_("  Shape read: fill0 (left) = %d"),
+                         current_path.getLeftFill());
+                );
+#endif
+            }
+            if ((flags & SHAPE_FILLSTYLE1_CHANGE) && num_fill_bits > 0)
+            {
+                // fill_style_1_change = 1;
+                if (! current_path.empty())
+                {
+                    _paths.push_back(current_path);
+                    current_path.m_edges.resize(0);
+                    current_path.ap.x = x;
+                    current_path.ap.y = y;
+                }
+                in.ensureBits(num_fill_bits);
+                unsigned style = in.read_uint(num_fill_bits);
+                if (style > 0)
+                {
+                    style += fill_base;
+                }
+    
+                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
+                {
+                    if ( style > 1 )          // 0:hide 1:renderer
+                    {
+                        IF_VERBOSE_MALFORMED_SWF(
+                             log_swferror(_("Invalid fill style %d in "
+                                     "fillStyle1Change record for font tag "
+                                     "(0 or 1 valid). Set to 0."), style);
+                        );
+                        style = 0;
+                    }
+                }
+                else
+                {
+                    // 1-based index
+                    if ( style > _fillStyles.size() )
+                    {
+                        IF_VERBOSE_MALFORMED_SWF(
+                            log_swferror(_("Invalid fill style %d in "
+                                    "fillStyle1Change record - %d defined. "
+                                    "Set to 0."), style, _fillStyles.size());
+                        );
+                        style = 0;
+                    }
+                }
+                current_path.setRightFill(style);
+#if SHAPE_LOG
+                IF_VERBOSE_PARSE (
+                    log_parse(_("  Shape read: fill1 (right) = %d"),
+                        current_path.getRightFill());
+                );
+#endif
+            }
+            if ((flags & SHAPE_LINESTYLE_CHANGE) && num_line_bits > 0)
+            {
+                // line_style_change = 1;
+                if (! current_path.empty())
+                {
+                    _paths.push_back(current_path);
+                    current_path.m_edges.resize(0);
+                    current_path.ap.x = x;
+                    current_path.ap.y = y;
+                }
+                in.ensureBits(num_line_bits);
+                unsigned style = in.read_uint(num_line_bits);
+                if (style > 0)
+                {
+                    style += line_base;
+                }
+                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
+                {
+                    if ( style > 1 )          // 0:hide 1:renderer
+                    {
+                        IF_VERBOSE_MALFORMED_SWF(
+                            log_swferror(_("Invalid line style %d in "
+                                    "lineStyleChange record for font tag "
+                                    "(0 or 1 valid). Set to 0."), style);
+                        );
+                        style = 0;
+                    }
+                }
+                else {
+                    // 1-based index
+                    if (style > _lineStyles.size()) {
+                        IF_VERBOSE_MALFORMED_SWF(
+                            log_swferror(_("Invalid fill style %d in "
+                                    "lineStyleChange record - %d defined. "
+                                    "Set to 0."), style, _lineStyles.size());
+                        );
+                        style = 0;
+                    }
+                }
+                current_path.setLineStyle(style);
+#if SHAPE_LOG
+                IF_VERBOSE_PARSE(
+                    log_parse(_("  Shape_read: line = %d"), 
+                        current_path.getLineStyle());
+                )
+#endif
+            }
+            if (flags & SHAPE_HAS_NEW_STYLES)
+            {
+                if (!styleInfo)
+                {
+                    IF_VERBOSE_MALFORMED_SWF(
+                         log_swferror("Unexpected HasNewStyle flag in tag "
+                             "%d shape record", tag);
+                    );
+                    continue;
+                }
+                IF_VERBOSE_PARSE (
+                    log_parse(_("  Shape read: more fill styles"));
+                );
+    
+                // Store the current path if any.
+                if (! current_path.empty())
+                {
+                    _paths.push_back(current_path);
+                    current_path.clear();
+                }
+    
+                // 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?
+                _paths.push_back(Path());
+                _paths.back().m_new_shape = true;
+    
+                fill_base = _fillStyles.size();
+                line_base = _lineStyles.size();
+                readFillStyles(_fillStyles, in, tag, m);
+                readLineStyles(_lineStyles, in, tag, m);
+    
+                in.ensureBits(8);
+                num_fill_bits = in.read_uint(4);
+                num_line_bits = in.read_uint(4);
+            }
+        }
+        else
+        {
+            // EDGERECORD
+            in.ensureBits(1);
+            bool edge_flag = in.read_bit();
+            if (edge_flag == 0)
+            {
+                in.ensureBits(4);
+                int num_bits = 2 + in.read_uint(4);
+                // curved edge
+                in.ensureBits(4 * num_bits);
+                int cx = x + in.read_sint(num_bits);
+                int cy = y + in.read_sint(num_bits);
+                int ax = cx + in.read_sint(num_bits);
+                int ay = cy + in.read_sint(num_bits);
+    
+#if SHAPE_LOG
+                IF_VERBOSE_PARSE (
+                    log_parse(_("  Shape read: curved edge   = "
+                            "%d %d - %d %d - %d %d"), x, y, cx, cy, ax, ay);
+                );
+#endif
+                current_path.m_edges.push_back(Edge(cx, cy, ax, ay));
+                x = ax;
+                y = ay;
+            }
+            else
+            {
+                // straight edge
+                in.ensureBits(5);
+                int num_bits = 2 + in.read_uint(4);
+                bool  line_flag = in.read_bit();
+                int dx = 0, dy = 0;
+                if (line_flag)
+                {
+                    // General line.
+                    in.ensureBits(2 * num_bits);
+                    dx = in.read_sint(num_bits);
+                    dy = in.read_sint(num_bits);
+                }
+                else
+                {
+                    in.ensureBits(1);
+                    bool vert_flag = in.read_bit();
+                    if (vert_flag == 0)
+                    {
+                        // Horizontal line.
+                        in.ensureBits(num_bits);
+                        dx = in.read_sint(num_bits);
+                    }
+                    else
+                    {
+                        // Vertical line.
+                        in.ensureBits(num_bits);
+                        dy = in.read_sint(num_bits);
+                    }
+                }
+    
+#if SHAPE_LOG
+                IF_VERBOSE_PARSE (
+                     log_parse(_("  Shape_read: straight edge = "
+                             "%d %d - %d %d"), x, y, x + dx, y + dy);
+                );
+#endif
+                current_path.m_edges.push_back(Edge(x + dx, y + dy,
+                            x + dx, y + dy));
+                x += dx;
+                y += dy;
+            }
+        }
+    }
+    
+    if (!styleInfo)
+    {
+        // TODO: performance would be improved by computing
+        //       the bounds as edges are parsed.
+        computeBounds(_bounds, _paths, _lineStyles, m.get_version());
+    }
+#ifdef GNASH_DEBUG_SHAPE_BOUNDS
+    else
+    {
+        rect computedBounds;
+        computeBounds(computedBounds, _paths, _lineStyles, m->get_version());
+        if ( computedBounds != m_bounds )
+        {
+            log_debug("Shape DisplayObject read for tag %d contained embedded "
+                    "bounds %s, while we computed bounds %s",
+                    tag, m_bound, computedBounds);
+        }
+    }
+#endif
+}
+
+namespace {
+
+// Read fill styles, and push them onto the given style array.
+void
+readFillStyles(ShapeRecord::FillStyles& styles, SWFStream& in,
+                 SWF::TagType tag, movie_definition& m)
+{
+    in.ensureBytes(1);
+    boost::uint16_t fill_style_count = in.read_u8();
+    if (tag != SWF::DEFINESHAPE)
+    {
+        if (fill_style_count == 0xFF)
+        {
+            in.ensureBytes(2);
+            fill_style_count = in.read_u16();
+        }
+    }
+
+    IF_VERBOSE_PARSE (
+        log_parse(_("  readFillStyles: count = %u"), fill_style_count);
+    );
+
+    // Read the styles.
+    styles.reserve(styles.size()+fill_style_count);
+    for (boost::uint16_t i = 0; i < fill_style_count; ++i)
+    {
+        // TODO: add a fill_style constructor directly reading from stream
+        fill_style fs;
+        fs.read(in, tag, m);
+        styles.push_back(fs);
+    }
+}
+
+// Read line styles and push them onto the back of the given array.
+void
+readLineStyles(ShapeRecord::LineStyles& styles, SWFStream& in,
+        SWF::TagType tag, movie_definition& md)
+{
+    in.ensureBytes(1);
+    int line_style_count = in.read_u8();
+
+    IF_VERBOSE_PARSE(
+        log_parse(_("  readLineStyles: count = %d"), line_style_count);
+    );
+
+    if (line_style_count == 0xFF)
+    {
+        in.ensureBytes(2);
+        line_style_count = in.read_u16();
+        IF_VERBOSE_PARSE(
+            log_parse(_("  readLineStyles: count2 = %d"), line_style_count);
+        );
+    }
+
+    // Read the styles.
+    for (int i = 0; i < line_style_count; i++)
+    {
+        styles.resize(styles.size() + 1);
+        styles.back().read(in, tag, md);
+    }
+}
+
+// Find the bounds of this shape, and store them in the given rectangle.
+void
+computeBounds(rect& bounds, const ShapeRecord::Paths& paths,
+        const ShapeRecord::LineStyles& lineStyles, int swfVersion)
+{
+    bounds.set_null();
+
+    for (unsigned int i = 0; i < paths.size(); i++)
+    {
+        const Path& p = paths[i];
+
+        unsigned thickness = 0;
+        if ( p.m_line )
+        {
+            // For glyph shapes m_line is allowed to be 1
+            // while no defined line styles are allowed.
+            if (lineStyles.empty()) {
+                // This is either a Glyph, for which m_line==1 is valid
+                // or a bug in the parser, which we have no way to
+                // check at this time
+                assert(p.m_line == 1);
+            }
+            else
+            {
+                thickness = lineStyles[p.m_line-1].getThickness();
+            }
+        }
+        p.expandBounds(bounds, thickness, swfVersion);
+    }
+}
+
+
+} // anonymous namespace
+
+} // namespace SWF
+} // namespace gnash
+

=== added file 'libcore/swf/ShapeRecord.h'
--- a/libcore/swf/ShapeRecord.h 1970-01-01 00:00:00 +0000
+++ b/libcore/swf/ShapeRecord.h 2009-04-07 14:32:06 +0000
@@ -0,0 +1,158 @@
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef GNASH_SWF_SHAPERECORD_H
+#define GNASH_SWF_SHAPERECORD_H
+
+#include "Geometry.h"
+#include "fill_style.h"
+#include "styles.h"
+#include "rect.h"
+
+#include <vector>
+
+
+namespace gnash {
+    class movie_definition;
+}
+
+namespace gnash {
+namespace SWF {
+
+/// Holds information needed to draw a shape.
+//
+/// This does not correspond exactly to parsed record in a SWF file, but
+/// is used to create both mutable and immutable shapes.
+//
+/// A ShapeRecord should have enough methods to implement the AS3 Graphics
+/// object (the drawing API of Shape and Sprite). This is restricted to
+/// adding fills, paths and line styles (which must be constructed outside
+/// this ShapeRecord before being added) and clearing everything. There
+/// is no support for removing single elements.
+//
+/// ShapeRecord objects are not ref-counted, so they may be stack-allocated
+/// or used in smart pointers.
+class ShapeRecord
+{
+public:
+
+    typedef std::vector<fill_style> FillStyles;
+    typedef std::vector<line_style> LineStyles;
+    typedef std::vector<Path> Paths;
+
+    /// Construct a ShapeRecord.
+    //
+    /// Ideally all immutable ShapeRecords should be constructed with the
+    /// ctor taking an SWFStream, but some tag formats do not allow this.
+    ShapeRecord() {}
+
+    /// Construct a ShapeRecord from a SWFStream.
+    //
+    /// This is useful for constructing immutable tags.
+    ShapeRecord(SWFStream& in, SWF::TagType tag, movie_definition& m);
+
+    ShapeRecord(const ShapeRecord& other)
+        :
+        _fillStyles(other._fillStyles),
+        _lineStyles(other._lineStyles),
+        _paths(other._paths),
+        _bounds(other._bounds)
+    {}
+
+    /// Parse path data from a SWFStream.
+    //
+    /// This is used by DefineMorphShapeTag as part of parsing its
+    /// more complex ShapeRecords.
+    void read(SWFStream& in, SWF::TagType tag, movie_definition& m);
+
+    const FillStyles& fillStyles() const {
+        return _fillStyles;
+    }
+    
+    const LineStyles& lineStyles() const {
+        return _lineStyles;
+    }
+
+    const Paths& paths() const {
+        return _paths;
+    }
+
+    const rect& getBounds() const {
+        return _bounds;
+    }
+
+    /// For DynamicShape
+    //
+    /// TODO: rewrite DynamicShape to push paths when they're
+    /// finished and drop this.
+    Path& currentPath() {
+        return _paths.back();
+    }
+
+    /// Set to the lerp of two ShapeRecords.
+    //
+    /// Used in shape morphing.
+    void setLerp(const ShapeRecord& a, const ShapeRecord& b,
+            const double ratio);
+
+    /// Reset all shape data.
+    void clear() {
+        _fillStyles.clear();
+        _lineStyles.clear();
+        _paths.clear();
+        _bounds.set_null();
+    }
+
+    void addFillStyle(const fill_style& fs) {
+        _fillStyles.push_back(fs);
+    }
+
+    void addPath(const Path& path) {
+        _paths.push_back(path);
+    }
+
+    void addLineStyle(const line_style& ls) {
+        _lineStyles.push_back(ls);
+    }
+
+    void setBounds(const rect& bounds) {
+        _bounds = bounds;
+    }
+
+private:
+    
+    /// Shape record flags for use in parsing.
+    enum ShapeRecordFlags {
+        SHAPE_END = 0x00,
+        SHAPE_MOVE = 0x01,
+        SHAPE_FILLSTYLE0_CHANGE = 0x02,
+        SHAPE_FILLSTYLE1_CHANGE = 0x04,
+        SHAPE_LINESTYLE_CHANGE = 0x08,
+        SHAPE_HAS_NEW_STYLES = 0x10
+    };
+    
+    FillStyles _fillStyles;
+    LineStyles _lineStyles;
+    Paths _paths;
+    rect _bounds;
+
+};
+
+} // namespace SWF
+} // namespace gnash
+
+#endif

=== modified file 'libcore/swf/TextRecord.cpp'
--- a/libcore/swf/TextRecord.cpp        2009-04-03 09:18:40 +0000
+++ b/libcore/swf/TextRecord.cpp        2009-04-07 11:14:10 +0000
@@ -144,14 +144,15 @@
 
 // Render the given glyph records.
 void
-TextRecord::displayRecords(const SWFMatrix& this_mat, DisplayObject* inst,
-    const std::vector<SWF::TextRecord>& records, bool embedded)
+TextRecord::displayRecords(const SWFMatrix& this_mat,
+        const DisplayObject& inst, const std::vector<SWF::TextRecord>& records,
+        bool embedded)
 {
 
-    SWFMatrix mat = inst->getWorldMatrix();
+    SWFMatrix mat = inst.getWorldMatrix();
     mat.concatenate(this_mat);
 
-    cxform cx = inst->get_world_cxform();
+    cxform cx = inst.get_world_cxform();
     const SWFMatrix base_matrix = mat;
 
     // Starting positions.
@@ -230,12 +231,12 @@
             }
             else
             {
-                shape_character_def* glyph = fnt->get_glyph(index, embedded);
+                ShapeRecord* glyph = fnt->get_glyph(index, embedded);
 
                 // Draw the DisplayObject using the filled outline.
                 if (glyph)
                 {
-                    render::draw_glyph(glyph, mat, textColor);
+                    render::drawGlyph(*glyph, textColor, mat);
                 }
             }
             x += ge.advance;

=== modified file 'libcore/swf/TextRecord.h'
--- a/libcore/swf/TextRecord.h  2009-04-03 09:18:40 +0000
+++ b/libcore/swf/TextRecord.h  2009-04-07 11:14:10 +0000
@@ -86,8 +86,10 @@
     bool read(SWFStream& in, movie_definition& m, int glyphBits,
             int advanceBits, TagType tag);
 
-    static void displayRecords(const SWFMatrix& this_mat, DisplayObject* inst,
-        const std::vector<SWF::TextRecord>& records, bool useEmbeddedGlyphs);
+    static void displayRecords(const SWFMatrix& this_mat,
+            const DisplayObject& inst,
+            const std::vector<SWF::TextRecord>& records,
+            bool useEmbeddedGlyphs);
 
     const Glyphs& glyphs() const {
         return _glyphs;

=== modified file 'libcore/swf/VideoFrameTag.cpp'
--- a/libcore/swf/VideoFrameTag.cpp     2009-04-03 09:18:40 +0000
+++ b/libcore/swf/VideoFrameTag.cpp     2009-04-07 12:46:29 +0000
@@ -36,14 +36,14 @@
     assert(tag == SWF::VIDEOFRAME);
 
     in.ensureBytes(2);
-    boost::uint16_t DisplayObject_id = in.read_u16();
-    character_def* chdef = m.get_character_def(DisplayObject_id);
+    boost::uint16_t id = in.read_u16();
+    DefinitionTag* chdef = m.getDefinitionTag(id);
 
     if (!chdef)
     {
         IF_VERBOSE_MALFORMED_SWF(
             log_swferror(_("VideoFrame tag refers to unknown video "
-                    "stream id %d"), DisplayObject_id);
+                    "stream id %d"), id);
         );
         return;
     }
@@ -53,7 +53,7 @@
     {
         IF_VERBOSE_MALFORMED_SWF(
         log_swferror(_("VideoFrame tag refers to a non-video DisplayObject "
-                "%d (%s)"), DisplayObject_id, typeName(*chdef));
+                "%d (%s)"), id, typeName(*chdef));
         );
         return;
     }

=== modified file 'libcore/swf/VideoFrameTag.h'
--- a/libcore/swf/VideoFrameTag.h       2009-04-03 09:18:40 +0000
+++ b/libcore/swf/VideoFrameTag.h       2009-04-07 12:34:43 +0000
@@ -24,7 +24,7 @@
 #include "gnashconfig.h"
 #endif
 
-#include "character_def.h"
+#include "DefinitionTag.h"
 #include "movie_definition.h"
 #include "swf.h"
 #include "rect.h" // for composition

=== modified file 'libcore/swf/tag_loaders.cpp'
--- a/libcore/swf/tag_loaders.cpp       2009-04-03 09:48:13 +0000
+++ b/libcore/swf/tag_loaders.cpp       2009-04-07 12:46:29 +0000
@@ -29,7 +29,6 @@
 #include "Font.h"
 #include "fontlib.h"
 #include "log.h"
-#include "morph2_character_def.h"
 #include "Geometry.h"
 #include "SWFStream.h"
 #include "styles.h"
@@ -285,13 +284,13 @@
     assert(tag == SWF::DEFINEBITS); // 6
 
     in.ensureBytes(2);
-    boost::uint16_t DisplayObject_id = in.read_u16();
+    boost::uint16_t id = in.read_u16();
 
-    if (m.getBitmap(DisplayObject_id))
+    if (m.getBitmap(id))
     {
         IF_VERBOSE_MALFORMED_SWF(
         log_swferror(_("DEFINEBITS: Duplicate id (%d) for bitmap DisplayObject 
"
-                "- discarding it"), DisplayObject_id);
+                "- discarding it"), id);
         );
         return;
     }
@@ -302,7 +301,7 @@
     {
         IF_VERBOSE_MALFORMED_SWF(
         log_swferror(_("DEFINEBITS: No jpeg loader registered in movie "
-                "definition - discarding bitmap DisplayObject %d"), 
DisplayObject_id);
+                "definition - discarding bitmap DisplayObject %d"), id);
         );
         return;
     }
@@ -318,7 +317,7 @@
     {
         IF_VERBOSE_MALFORMED_SWF(
         log_swferror("Error reading jpeg2 with headers for DisplayObject "
-            "id %d: %s", DisplayObject_id, e.what());
+            "id %d: %s", id, e.what());
         );
         return;
     }
@@ -326,7 +325,7 @@
     boost::intrusive_ptr<BitmapInfo> bi = render::createBitmapInfo(im);
 
     // add bitmap to movie under DisplayObject id.
-    m.addBitmap(DisplayObject_id, bi);
+    m.addBitmap(id, bi);
 }
 
 
@@ -337,20 +336,20 @@
     assert(tag == SWF::DEFINEBITSJPEG2); // 21
 
     in.ensureBytes(2);
-    boost::uint16_t DisplayObject_id = in.read_u16();
+    boost::uint16_t id = in.read_u16();
 
     IF_VERBOSE_PARSE
     (
     log_parse(_("  define_bits_jpeg2_loader: charid = %d pos = %ld"),
-          DisplayObject_id, in.tell());
+          id, in.tell());
     );
 
     
-    if ( m.getBitmap(DisplayObject_id) )
+    if ( m.getBitmap(id) )
     {
         IF_VERBOSE_MALFORMED_SWF(
         log_swferror(_("DEFINEBITSJPEG2: Duplicate id (%d) for bitmap "
-                "DisplayObject - discarding it"), DisplayObject_id);
+                "DisplayObject - discarding it"), id);
         );
         return;
     }
@@ -366,7 +365,7 @@
     boost::intrusive_ptr<BitmapInfo> bi = render::createBitmapInfo(im);
 
     // add bitmap to movie under DisplayObject id.
-    m.addBitmap(DisplayObject_id, bi);
+    m.addBitmap(id, bi);
 
 }
 
@@ -468,12 +467,12 @@
     assert(tag == SWF::DEFINEBITSJPEG3); // 35
 
     in.ensureBytes(2);
-    boost::uint16_t DisplayObject_id = in.read_u16();
+    boost::uint16_t id = in.read_u16();
 
     IF_VERBOSE_PARSE
     (
     log_parse(_("  define_bits_jpeg3_loader: charid = %d pos = %lx"),
-          DisplayObject_id, in.tell());
+          id, in.tell());
     );
 
     in.ensureBytes(4);
@@ -516,7 +515,7 @@
         render::createBitmapInfo(static_cast<std::auto_ptr<GnashImage> >(im));
 
     // add bitmap to movie under DisplayObject id.
-    m.addBitmap(DisplayObject_id, bi);
+    m.addBitmap(id, bi);
 #endif
 }
 
@@ -530,7 +529,7 @@
 
     in.ensureBytes(2+2+2+1); // the initial header 
 
-    boost::uint16_t DisplayObject_id = in.read_u16();
+    boost::uint16_t id = in.read_u16();
 
     // 3 == 8 bit, 4 == 16 bit, 5 == 32 bit
     boost::uint8_t bitmap_format = in.read_u8();
@@ -540,25 +539,25 @@
     IF_VERBOSE_PARSE(
         log_parse(_("  defbitslossless2: tag = %d, id = %d, "
             "fmt = %d, w = %d, h = %d"),
-            tag, DisplayObject_id, bitmap_format, width, height);
+            tag, id, bitmap_format, width, height);
     );
 
     if (!width || !height) {
          IF_VERBOSE_MALFORMED_SWF(
             log_swferror(_("Bitmap DisplayObject %d has a height or width of 
0"),
-                DisplayObject_id);
+                id);
         );   
         return;  
     }
 
     // No need to parse any further if it already exists, as we aren't going
     // to add it.
-    if (m.getBitmap(DisplayObject_id))
+    if (m.getBitmap(id))
     {
         IF_VERBOSE_MALFORMED_SWF(
             log_swferror(_("DEFINEBITSLOSSLESS: Duplicate id (%d) "
                            "for bitmap DisplayObject - discarding it"),
-                DisplayObject_id);
+                id);
         );
     }
 
@@ -703,7 +702,7 @@
     boost::intrusive_ptr<BitmapInfo> bi = render::createBitmapInfo(image);
 
     // add bitmap to movie under DisplayObject id.
-    m.addBitmap(DisplayObject_id, bi);
+    m.addBitmap(id, bi);
 #endif // HAVE_ZLIB_H
 
 }
@@ -719,45 +718,6 @@
     }
 }
 
-void define_shape_loader(SWFStream& in, TagType tag, movie_definition& m,
-               const RunInfo& /*r*/)
-{
-    assert(tag == SWF::DEFINESHAPE
-       || tag == SWF::DEFINESHAPE2
-       || tag == SWF::DEFINESHAPE3
-       || tag == SWF::DEFINESHAPE4 || tag == SWF::DEFINESHAPE4_);
-
-    in.ensureBytes(2);
-    boost::uint16_t    DisplayObject_id = in.read_u16();
-    IF_VERBOSE_PARSE(
-        log_parse(_("  shape_loader: id = %d"), DisplayObject_id);
-    );
-
-    shape_character_def* ch = new shape_character_def;
-    ch->read(in, tag, true, m);
-
-    m.addDisplayObject(DisplayObject_id, ch);
-}
-
-void define_shape_morph_loader(SWFStream& in, TagType tag, movie_definition& m,
-               const RunInfo& /*r*/)
-{
-    assert(tag == SWF::DEFINEMORPHSHAPE
-        || tag == SWF::DEFINEMORPHSHAPE2
-        || tag == SWF::DEFINEMORPHSHAPE2_); 
-
-    in.ensureBytes(2);
-    boost::uint16_t DisplayObject_id = in.read_u16();
-
-    IF_VERBOSE_PARSE(
-        log_parse(_("  shape_morph_loader: id = %d"), DisplayObject_id);
-    );
-
-    morph2_character_def* morph = new morph2_character_def;
-    morph->read(in, tag, m);
-    m.addDisplayObject(DisplayObject_id, morph);
-}
-
 // Create and initialize a sprite, and add it to the movie.
 void
 sprite_loader(SWFStream& in, TagType tag, movie_definition& m,
@@ -766,11 +726,11 @@
     assert(tag == SWF::DEFINESPRITE); // 39 - DefineSprite
 
     in.ensureBytes(2);
-    int    DisplayObject_id = in.read_u16();
+    int    id = in.read_u16();
 
     IF_VERBOSE_PARSE
     (
-    log_parse(_("  sprite:  char id = %d"), DisplayObject_id);
+    log_parse(_("  sprite:  char id = %d"), id);
     );
 
     // A DEFINESPRITE tag as part of a DEFINESPRITE
@@ -791,12 +751,12 @@
 
     IF_VERBOSE_MALFORMED_SWF(
         if (!ch->get_frame_count()) {
-            log_swferror(_("Sprite %d advertise no frames"), DisplayObject_id);
+            log_swferror(_("Sprite %d advertise no frames"), id);
         }
     );
 
 
-    m.addDisplayObject(DisplayObject_id, ch);
+    m.addDisplayObject(id, ch);
 }
 
 
@@ -847,7 +807,7 @@
         // Fonts, DisplayObjects and sounds can be exported.
         ExportableResource* f;
         if ((f = m.get_font(id)) ||
-            (f = m.get_character_def(id)) ||
+            (f = m.getDefinitionTag(id)) ||
             (f = m.get_sound_sample(id))) {
             
             m.export_resource(symbolName, f);
@@ -976,7 +936,7 @@
 
     in.ensureBytes(2+4+1+4); // DisplayObject id + flags + sample count
 
-    boost::uint16_t    DisplayObject_id = in.read_u16();
+    boost::uint16_t    id = in.read_u16();
 
     media::audioCodecType format = static_cast<media::audioCodecType>(
             in.read_uint(4));
@@ -1024,7 +984,7 @@
     (
         log_parse(_("define sound: ch=%d, format=%s, "
             "rate=%d, 16=%d, stereo=%d, ct=%d"),
-              DisplayObject_id, format, sample_rate,
+              id, format, sample_rate,
               int(sample_16bit), int(stereo), sample_count);
     );
 
@@ -1067,7 +1027,7 @@
         if (handler_id >= 0)
         {
         sound_sample* sam = new sound_sample(handler_id, r);
-        m.add_sound_sample(DisplayObject_id, sam);
+        m.add_sound_sample(id, sam);
         }
 
     }
@@ -1077,7 +1037,7 @@
         log_error(_("There is no sound handler currently active, "
             "so DisplayObject with id %d will NOT be added to "
             "the dictionary"),
-              DisplayObject_id);
+              id);
     }
 }
 

=== modified file 'libcore/swf/tag_loaders.h'
--- a/libcore/swf/tag_loaders.h 2009-01-22 20:10:39 +0000
+++ b/libcore/swf/tag_loaders.h 2009-04-07 12:45:25 +0000
@@ -63,20 +63,11 @@
 void define_bits_jpeg3_loader(SWFStream&, TagType, movie_definition&,
                const RunInfo&);
 
-void define_shape_loader(SWFStream&, TagType, movie_definition&,
-               const RunInfo&);
-
-void define_shape_morph_loader(SWFStream&, TagType, movie_definition&,
-               const RunInfo&);
-
 /// SWF Tags Reflex (777)
 //
 void reflex_loader(SWFStream&, TagType, movie_definition&,
                const RunInfo&);
 
-void place_object_2_loader(SWFStream&, TagType, movie_definition&,
-               const RunInfo&);
-
 void define_bits_lossless_2_loader(SWFStream&, TagType, movie_definition&,
                const RunInfo&);
 

=== modified file 'testsuite/Makefile.am'
--- a/testsuite/Makefile.am     2009-03-24 10:21:30 +0000
+++ b/testsuite/Makefile.am     2009-04-07 09:19:54 +0000
@@ -111,6 +111,7 @@
        -I$(top_srcdir)/libsound \
        -I$(top_srcdir)/backend \
        -I$(top_srcdir)/libcore  \
+       -I$(top_srcdir)/libcore/swf  \
        -I$(top_srcdir)/libcore/parser  \
        -I$(top_srcdir)/libcore/vm  \
        $(BOOST_CFLAGS) \

=== modified file 'testsuite/libcore.all/ClassSizes.cpp'
--- a/testsuite/libcore.all/ClassSizes.cpp      2009-04-03 09:29:19 +0000
+++ b/testsuite/libcore.all/ClassSizes.cpp      2009-04-07 16:32:11 +0000
@@ -27,6 +27,11 @@
 #include "DisplayObject.h"
 #include "RGBA.h"
 #include "movie_root.h"
+#include "swf/ShapeRecord.h"
+#include "StaticText.h"
+#include "Button.h"
+#include "MorphShape.h"
+#include "Shape.h"
 
 #include <iostream>
 #include <sstream>
@@ -69,5 +74,11 @@
        std::cout << "sizeof(fill_style): " << (sizeof(fill_style)) << 
std::endl;
        std::cout << "sizeof(SWFMatrix): " << (sizeof(SWFMatrix)) << std::endl;
        std::cout << "sizeof(movie_root): " << (sizeof(movie_root)) << 
std::endl;
+       
+    std::cout << "sizeof(ShapeRecord): " << (sizeof(SWF::ShapeRecord)) << 
std::endl;
+       std::cout << "sizeof(StaticText): " << (sizeof(StaticText)) << 
std::endl;
+       std::cout << "sizeof(MorphShape): " << (sizeof(MorphShape)) << 
std::endl;
+       std::cout << "sizeof(Shape): " << (sizeof(Shape)) << std::endl;
+       std::cout << "sizeof(Button): " << (sizeof(Button)) << std::endl;
 }
 

=== modified file 'testsuite/libcore.all/EdgeTest.cpp'
--- a/testsuite/libcore.all/EdgeTest.cpp        2009-03-10 20:43:50 +0000
+++ b/testsuite/libcore.all/EdgeTest.cpp        2009-04-06 11:31:51 +0000
@@ -64,13 +64,13 @@
        // Test distance
        //
 
-       check_equals(edge::distancePtSeg(point(0,0), point(9, 0), point(9, 0)), 
9);
-       check_equals(edge::distancePtSeg(point(0,0), point(0, 0), point(3, 0)), 
0);
-       check_equals(edge::distancePtSeg(point(-5,0), point(0, 0), point(3, 
0)), 5);
-       check_equals(edge::distancePtSeg(point(5,0), point(0, 0), point(3, 0)), 
2);
-       check_equals(D(edge::distancePtSeg(point(0,0), point(-10, 0), point(3, 
0))), 0);
-       check_equals(edge::distancePtSeg(point(0,0), point(-10, 0), point(-10, 
30)), 10);
-       check_equals(edge::distancePtSeg(point(5,5), point(-10, 0), point(10, 
0)), 5);
+       check_equals(Edge::distancePtSeg(point(0,0), point(9, 0), point(9, 0)), 
9);
+       check_equals(Edge::distancePtSeg(point(0,0), point(0, 0), point(3, 0)), 
0);
+       check_equals(Edge::distancePtSeg(point(-5,0), point(0, 0), point(3, 
0)), 5);
+       check_equals(Edge::distancePtSeg(point(5,0), point(0, 0), point(3, 0)), 
2);
+       check_equals(D(Edge::distancePtSeg(point(0,0), point(-10, 0), point(3, 
0))), 0);
+       check_equals(Edge::distancePtSeg(point(0,0), point(-10, 0), point(-10, 
30)), 10);
+       check_equals(Edge::distancePtSeg(point(5,5), point(-10, 0), point(10, 
0)), 5);
 
        //
        // Test pointOnCurve
@@ -84,11 +84,11 @@
        point A(10, 10);
        point C(20, 10);
        point B(20, 20);
-       check_equals(edge::pointOnCurve(A, C, B, 0), A);
-       check_equals(edge::pointOnCurve(A, C, B, 1), B);
-       check_equals(edge::pointOnCurve(A, C, B, 0.5), point(17.5, 12.5));
-       check_equals(sqrt((float)edge::squareDistancePtCurve(A, C, B, B, 1)), 
0);
-       check_equals(sqrt((float)edge::squareDistancePtCurve(A, C, B, A, 0)), 
0);
+       check_equals(Edge::pointOnCurve(A, C, B, 0), A);
+       check_equals(Edge::pointOnCurve(A, C, B, 1), B);
+       check_equals(Edge::pointOnCurve(A, C, B, 0.5), point(17.5, 12.5));
+       check_equals(sqrt((float)Edge::squareDistancePtCurve(A, C, B, B, 1)), 
0);
+       check_equals(sqrt((float)Edge::squareDistancePtCurve(A, C, B, A, 0)), 
0);
 
        //
        // A----B---C
@@ -96,10 +96,10 @@
        A.setTo(10, 10);
        C.setTo(40, 10);
        B.setTo(20, 10);
-       check_equals(edge::pointOnCurve(A, C, B, 0), A);
-       check_equals(edge::pointOnCurve(A, C, B, 1), B);
-       check_equals(edge::pointOnCurve(A, C, B, 0.5), point(27.5, 10));
-       check_equals(sqrt((float)edge::squareDistancePtCurve(A, C, B, B, 1)), 
0);
-       check_equals(sqrt((float)edge::squareDistancePtCurve(A, C, B, A, 0)), 
0);
+       check_equals(Edge::pointOnCurve(A, C, B, 0), A);
+       check_equals(Edge::pointOnCurve(A, C, B, 1), B);
+       check_equals(Edge::pointOnCurve(A, C, B, 0.5), point(27.5, 10));
+       check_equals(sqrt((float)Edge::squareDistancePtCurve(A, C, B, B, 1)), 
0);
+       check_equals(sqrt((float)Edge::squareDistancePtCurve(A, C, B, A, 0)), 
0);
 }
 

=== modified file 'testsuite/libcore.all/Makefile.am'
--- a/testsuite/libcore.all/Makefile.am 2009-03-19 22:18:46 +0000
+++ b/testsuite/libcore.all/Makefile.am 2009-04-07 16:32:11 +0000
@@ -25,6 +25,7 @@
         -I$(top_srcdir)/libnet  \
         -I$(top_srcdir)/libbase  \
         -I$(top_srcdir)/libcore  \
+        -I$(top_srcdir)/libcore/swf \
         -I$(top_srcdir)/libcore/parser  \
         -I$(top_srcdir)/libcore/vm  \
        $(FFMPEG_CFLAGS) \

=== modified file 'testsuite/misc-ming.all/Makefile.am'
--- a/testsuite/misc-ming.all/Makefile.am       2009-03-18 17:47:08 +0000
+++ b/testsuite/misc-ming.all/Makefile.am       2009-04-07 09:19:54 +0000
@@ -55,6 +55,7 @@
        -I$(top_srcdir)/libsound \
        -I$(top_srcdir)/backend \
        -I$(top_srcdir)/libcore  \
+       -I$(top_srcdir)/libcore/swf  \
        -I$(top_srcdir)/libcore/parser  \
        -I$(top_srcdir)/libcore/vm \
        -I$(top_srcdir)/libcore/asobj \

=== modified file 'testsuite/misc-swfc.all/Makefile.am'
--- a/testsuite/misc-swfc.all/Makefile.am       2009-02-25 22:33:03 +0000
+++ b/testsuite/misc-swfc.all/Makefile.am       2009-04-07 11:14:10 +0000
@@ -58,6 +58,7 @@
         -I$(top_srcdir)/libsound \
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/libcore  \
+        -I$(top_srcdir)/libcore/swf  \
         -I$(top_srcdir)/libcore/vm  \
         -I$(top_srcdir)/libcore/parser  \
         -I$(top_srcdir)/testsuite \

=== modified file 'testsuite/misc-swfmill.all/Makefile.am'
--- a/testsuite/misc-swfmill.all/Makefile.am    2009-02-25 22:33:03 +0000
+++ b/testsuite/misc-swfmill.all/Makefile.am    2009-04-07 11:14:10 +0000
@@ -42,6 +42,7 @@
        -I$(top_srcdir)/libsound \
        -I$(top_srcdir)/backend \
        -I$(top_srcdir)/libcore  \
+       -I$(top_srcdir)/libcore/swf \
        -I$(top_srcdir)/libcore/parser  \
        -I$(top_srcdir)/libcore/vm \
        -I$(top_srcdir)/libcore/asobj \

=== modified file 'testsuite/movies.all/Makefile.am'
--- a/testsuite/movies.all/Makefile.am  2009-02-25 22:33:03 +0000
+++ b/testsuite/movies.all/Makefile.am  2009-04-07 09:49:53 +0000
@@ -39,6 +39,7 @@
        -I$(top_srcdir)/libsound \
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/libcore  \
+        -I$(top_srcdir)/libcore/swf  \
         -I$(top_srcdir)/libcore/parser  \
        -I$(top_srcdir)/libcore/vm \
        -I$(top_srcdir)/libcore/asobj \

=== modified file 'testsuite/samples/Makefile.am'
--- a/testsuite/samples/Makefile.am     2009-02-25 22:33:03 +0000
+++ b/testsuite/samples/Makefile.am     2009-04-07 09:49:53 +0000
@@ -32,6 +32,7 @@
        -I$(top_srcdir)/libsound \
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/libcore  \
+        -I$(top_srcdir)/libcore/swf \
         -I$(top_srcdir)/libcore/parser  \
         -I$(top_srcdir)/libcore/vm  \
         -I$(top_srcdir)/testsuite \

=== modified file 'utilities/Makefile.am'
--- a/utilities/Makefile.am     2009-02-02 02:07:06 +0000
+++ b/utilities/Makefile.am     2009-04-06 20:29:42 +0000
@@ -54,6 +54,7 @@
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/libcore \
         -I$(top_srcdir)/libcore/asobj \
+        -I$(top_srcdir)/libcore/swf \
         -I$(top_srcdir)/libcore/parser \
         -I$(top_srcdir)/libcore/vm \
         -I$(top_srcdir)/libmedia \


reply via email to

[Prev in Thread] Current Thread [Next in Thread]