From 08274f0a0ceebb84df82ef42b2d5833e03e6adcc Mon Sep 17 00:00:00 2001
From: Rodrigo Braz Monteiro <zeratul@cellosoft.com>
Date: Wed, 23 Jan 2008 02:22:15 +0000
Subject: [PATCH] Committed a (broken) copy of ASSDraw3 source code by ai-chan

Originally committed to SVN as r1815.
---
 assdraw/assdraw.vcproj                   |  317 ++++
 assdraw/src/ASSDraw3.dev                 |  323 ++++
 assdraw/src/ASSDraw3.layout              |  185 ++
 assdraw/src/Makefile.win                 |   69 +
 assdraw/src/_common.hpp                  |   14 +
 assdraw/src/agg_bcspline.cpp             |  289 +++
 assdraw/src/agg_bcspline.h               |   81 +
 assdraw/src/agg_conv_bcspline.h          |   58 +
 assdraw/src/agg_vcgen_bcspline.cpp       |  203 +++
 assdraw/src/agg_vcgen_bcspline.h         |   83 +
 assdraw/src/agghelper.hpp                |   20 +
 assdraw/src/assdraw.cpp                  |  768 ++++++++
 assdraw/src/assdraw.hpp                  |  208 +++
 assdraw/src/assdraw.rc                   |  101 ++
 assdraw/src/assdraw_settings.cpp         |  190 ++
 assdraw/src/bitmaps/Copy of assdraw3.bmp |  Bin 0 -> 86454 bytes
 assdraw/src/bitmaps/add_.bmp             |  Bin 0 -> 774 bytes
 assdraw/src/bitmaps/arr_.bmp             |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/arr_1.bmp            |  Bin 0 -> 774 bytes
 assdraw/src/bitmaps/assdraw3.bmp         |  Bin 0 -> 120054 bytes
 assdraw/src/bitmaps/b_.bmp               |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/b_.cur               |  Bin 0 -> 4286 bytes
 assdraw/src/bitmaps/c_.bmp               |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/check_.bmp           |  Bin 0 -> 774 bytes
 assdraw/src/bitmaps/del_.bmp             |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/del_cross.bmp        |  Bin 0 -> 774 bytes
 assdraw/src/bitmaps/help.bmp             |  Bin 0 -> 1318 bytes
 assdraw/src/bitmaps/help_.bmp            |  Bin 0 -> 774 bytes
 assdraw/src/bitmaps/l_.bmp               |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/m_.bmp               |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/n_.bmp               |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/new_.bmp             |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/nut_.bmp             |  Bin 0 -> 774 bytes
 assdraw/src/bitmaps/p_.bmp               |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/pan_bg.bmp           |  Bin 0 -> 1134 bytes
 assdraw/src/bitmaps/pan_both.bmp         |  Bin 0 -> 1134 bytes
 assdraw/src/bitmaps/pan_shape.bmp        |  Bin 0 -> 1434 bytes
 assdraw/src/bitmaps/pan_shp.bmp          |  Bin 0 -> 1134 bytes
 assdraw/src/bitmaps/preview_.bmp         |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/rot_.bmp             |  Bin 0 -> 774 bytes
 assdraw/src/bitmaps/s_.bmp               |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/sc_rot_.bmp          |  Bin 0 -> 774 bytes
 assdraw/src/bitmaps/src_.bmp             |  Bin 0 -> 776 bytes
 assdraw/src/bitmaps/transform.bmp        |  Bin 0 -> 25144 bytes
 assdraw/src/bitmaps/uncheck_.bmp         |  Bin 0 -> 774 bytes
 assdraw/src/canvas.cpp                   | 2057 ++++++++++++++++++++++
 assdraw/src/canvas.hpp                   |  303 ++++
 assdraw/src/canvas_mouse.cpp             |   56 +
 assdraw/src/canvas_mouse.hpp             |   85 +
 assdraw/src/cmd.cpp                      |  212 +++
 assdraw/src/cmd.hpp                      |  112 ++
 assdraw/src/dlgctrl.cpp                  |  372 ++++
 assdraw/src/dlgctrl.hpp                  |  115 ++
 assdraw/src/engine.cpp                   |  749 ++++++++
 assdraw/src/engine.hpp                   |  406 +++++
 assdraw/src/enums.hpp                    |  113 ++
 assdraw/src/include_once.hpp             |   94 +
 assdraw/src/library.cpp                  |  259 +++
 assdraw/src/library.hpp                  |   88 +
 assdraw/src/resource.h                   |   15 +
 assdraw/src/settings.cpp                 |  223 +++
 assdraw/src/settings.hpp                 |  119 ++
 assdraw/src/tsukasa.ico                  |  Bin 0 -> 17574 bytes
 assdraw/src/wxAGG/AGGWindow.cpp          |  124 ++
 assdraw/src/wxAGG/AGGWindow.h            |   68 +
 assdraw/src/wxAGG/PixelFormatConvertor.h |  117 ++
 66 files changed, 8596 insertions(+)
 create mode 100644 assdraw/assdraw.vcproj
 create mode 100644 assdraw/src/ASSDraw3.dev
 create mode 100644 assdraw/src/ASSDraw3.layout
 create mode 100644 assdraw/src/Makefile.win
 create mode 100644 assdraw/src/_common.hpp
 create mode 100644 assdraw/src/agg_bcspline.cpp
 create mode 100644 assdraw/src/agg_bcspline.h
 create mode 100644 assdraw/src/agg_conv_bcspline.h
 create mode 100644 assdraw/src/agg_vcgen_bcspline.cpp
 create mode 100644 assdraw/src/agg_vcgen_bcspline.h
 create mode 100644 assdraw/src/agghelper.hpp
 create mode 100644 assdraw/src/assdraw.cpp
 create mode 100644 assdraw/src/assdraw.hpp
 create mode 100644 assdraw/src/assdraw.rc
 create mode 100644 assdraw/src/assdraw_settings.cpp
 create mode 100644 assdraw/src/bitmaps/Copy of assdraw3.bmp
 create mode 100644 assdraw/src/bitmaps/add_.bmp
 create mode 100644 assdraw/src/bitmaps/arr_.bmp
 create mode 100644 assdraw/src/bitmaps/arr_1.bmp
 create mode 100644 assdraw/src/bitmaps/assdraw3.bmp
 create mode 100644 assdraw/src/bitmaps/b_.bmp
 create mode 100644 assdraw/src/bitmaps/b_.cur
 create mode 100644 assdraw/src/bitmaps/c_.bmp
 create mode 100644 assdraw/src/bitmaps/check_.bmp
 create mode 100644 assdraw/src/bitmaps/del_.bmp
 create mode 100644 assdraw/src/bitmaps/del_cross.bmp
 create mode 100644 assdraw/src/bitmaps/help.bmp
 create mode 100644 assdraw/src/bitmaps/help_.bmp
 create mode 100644 assdraw/src/bitmaps/l_.bmp
 create mode 100644 assdraw/src/bitmaps/m_.bmp
 create mode 100644 assdraw/src/bitmaps/n_.bmp
 create mode 100644 assdraw/src/bitmaps/new_.bmp
 create mode 100644 assdraw/src/bitmaps/nut_.bmp
 create mode 100644 assdraw/src/bitmaps/p_.bmp
 create mode 100644 assdraw/src/bitmaps/pan_bg.bmp
 create mode 100644 assdraw/src/bitmaps/pan_both.bmp
 create mode 100644 assdraw/src/bitmaps/pan_shape.bmp
 create mode 100644 assdraw/src/bitmaps/pan_shp.bmp
 create mode 100644 assdraw/src/bitmaps/preview_.bmp
 create mode 100644 assdraw/src/bitmaps/rot_.bmp
 create mode 100644 assdraw/src/bitmaps/s_.bmp
 create mode 100644 assdraw/src/bitmaps/sc_rot_.bmp
 create mode 100644 assdraw/src/bitmaps/src_.bmp
 create mode 100644 assdraw/src/bitmaps/transform.bmp
 create mode 100644 assdraw/src/bitmaps/uncheck_.bmp
 create mode 100644 assdraw/src/canvas.cpp
 create mode 100644 assdraw/src/canvas.hpp
 create mode 100644 assdraw/src/canvas_mouse.cpp
 create mode 100644 assdraw/src/canvas_mouse.hpp
 create mode 100644 assdraw/src/cmd.cpp
 create mode 100644 assdraw/src/cmd.hpp
 create mode 100644 assdraw/src/dlgctrl.cpp
 create mode 100644 assdraw/src/dlgctrl.hpp
 create mode 100644 assdraw/src/engine.cpp
 create mode 100644 assdraw/src/engine.hpp
 create mode 100644 assdraw/src/enums.hpp
 create mode 100644 assdraw/src/include_once.hpp
 create mode 100644 assdraw/src/library.cpp
 create mode 100644 assdraw/src/library.hpp
 create mode 100644 assdraw/src/resource.h
 create mode 100644 assdraw/src/settings.cpp
 create mode 100644 assdraw/src/settings.hpp
 create mode 100644 assdraw/src/tsukasa.ico
 create mode 100644 assdraw/src/wxAGG/AGGWindow.cpp
 create mode 100644 assdraw/src/wxAGG/AGGWindow.h
 create mode 100644 assdraw/src/wxAGG/PixelFormatConvertor.h

diff --git a/assdraw/assdraw.vcproj b/assdraw/assdraw.vcproj
new file mode 100644
index 000000000..f61c1636a
--- /dev/null
+++ b/assdraw/assdraw.vcproj
@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="assdraw"
+	ProjectGUID="{3BC75951-691C-4703-A29A-D29E298248AC}"
+	RootNamespace="assdraw"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\src\agg_bcspline.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\agg_vcgen_bcspline.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\wxAGG\AGGWindow.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\assdraw.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\assdraw_settings.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\canvas.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\canvas_mouse.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\cmd.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\dlgctrl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\engine.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\library.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\settings.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\src\_common.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\agg_bcspline.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\agg_conv_bcspline.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\agg_vcgen_bcspline.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\agghelper.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\wxAGG\AGGWindow.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\assdraw.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\canvas.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\canvas_mouse.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\cmd.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\dlgctrl.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\engine.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\enums.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\include_once.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\library.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\wxAGG\PixelFormatConvertor.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\settings.hpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\src\assdraw.rc"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/assdraw/src/ASSDraw3.dev b/assdraw/src/ASSDraw3.dev
new file mode 100644
index 000000000..5afb0aa92
--- /dev/null
+++ b/assdraw/src/ASSDraw3.dev
@@ -0,0 +1,323 @@
+[Project]
+FileName=ASSDraw3.dev
+Name=ASSDraw
+UnitCount=26
+Type=0
+Ver=3
+IsCpp=1
+Folders=AGG
+CommandLine=
+CompilerSettings=0000000001001000000100
+PchHead=-1
+PchSource=-1
+ProfilesCount=1
+ProfileIndex=0
+
+[Unit1]
+FileName=assdraw.cpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=3
+Minor=0
+Release=0
+Build=0
+LanguageID=1033
+CharsetID=1252
+CompanyName=ai-chan
+FileVersion=3.0.0.0
+FileDescription=A tool for designing shapes to be used in ASS subtitle
+InternalName=ASSDraw3
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=ASSDraw3.exe
+ProductName=ASSDraw
+ProductVersion=3
+AutoIncBuildNrOnRebuild=0
+AutoIncBuildNrOnCompile=0
+UnitCount=20
+
+[Unit3]
+FileName=cmd.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=engine.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=assdraw.rc
+CompileCpp=1
+Folder=Resources
+Compile=1
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit7]
+FileName=engine.cpp
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+CompileCpp=1
+
+[Unit9]
+FileName=include_once.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=assdraw.hpp
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+CompileCpp=1
+
+[Unit2]
+FileName=cmd.cpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Profile1]
+ProfileName=Default Profile
+Type=0
+ObjFiles=
+Includes=E:\DEV;E:\DEV\agg-2.5\include;E:\DEV\wxTreeMultiCtrl\include
+Libs=E:\DEV\agg-2.5;E:\DEV\wxTreeMultiCtrl
+PrivateResource=E:\DEV\_projects\ASSDraw 3\Default Profile\ASSDraw_private.rc
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=-D__WXMSW__ -DNO_GCC_PRAGMA -fno-rtti -fno-exceptions_@@_ -Wno-deprecated_@@_
+Linker=-lwxmsw28_propgrid_@@_-mwindows_@@_-lwxmsw28_@@_-lwxmsw28_gl_@@_-lwxtiff_@@_-lwxjpeg_@@_-lwxpng_@@_-lwxzlib_@@_-lwxregex_@@_-lwxexpat_@@_-lkernel32_@@_-luser32_@@_-lgdi32_@@_-lcomdlg32_@@_-lwinspool_@@_-lwinmm_@@_-lshell32_@@_-lcomctl32_@@_-lole32_@@_-loleaut32_@@_-luuid_@@_-lrpcrt4_@@_-ladvapi32_@@_-lwsock32_@@_-lodbc32_@@_-lopengl32_@@_-lagg_@@_
+PreprocDefines=
+CompilerSettings=0000000001001000000100
+Icon=
+ExeOutput=E:\DEV\_projects\ASSDraw 3\Default Profile\
+ObjectOutput=E:\DEV\_projects\ASSDraw 3\Default Profile\
+OverrideOutput=1
+OverrideOutputName=ASSDraw3.exe
+HostApplication=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=1
+SupportXPThemes=1
+CompilerSet=0
+compilerType=0
+
+[Unit8]
+FileName=dlgctrl.cpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit10]
+FileName=resource.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit15]
+FileName=agg_bcspline.cpp
+CompileCpp=1
+Folder=AGG
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit16]
+FileName=enums.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit18]
+FileName=library.cpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit17]
+FileName=library.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit13]
+FileName=wxAGG\AGGWindow.cpp
+CompileCpp=1
+Folder=AGG
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit14]
+FileName=agg_vcgen_bcspline.cpp
+CompileCpp=1
+Folder=AGG
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit11]
+FileName=canvas.cpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit12]
+FileName=canvas.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit20]
+FileName=dlgctrl.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit19]
+FileName=_common.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit21]
+FileName=settings.cpp
+CompileCpp=1
+Folder=ASSDraw
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit22]
+FileName=settings.hpp
+CompileCpp=1
+Folder=ASSDraw
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit23]
+FileName=assdraw_settings.cpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit24]
+FileName=agghelper.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit25]
+FileName=canvas_mouse.hpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit26]
+FileName=canvas_mouse.cpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/assdraw/src/ASSDraw3.layout b/assdraw/src/ASSDraw3.layout
new file mode 100644
index 000000000..8ed9b9f28
--- /dev/null
+++ b/assdraw/src/ASSDraw3.layout
@@ -0,0 +1,185 @@
+[Editor_10]
+CursorCol=32
+CursorRow=553
+TopLine=535
+LeftChar=1
+Open=1
+Top=0
+[Editor_7]
+CursorCol=6
+CursorRow=227
+TopLine=197
+LeftChar=1
+Open=1
+Top=1
+[Editor_5]
+CursorCol=11
+CursorRow=19
+TopLine=1
+LeftChar=1
+Open=1
+Top=0
+[Editor_18]
+CursorCol=11
+CursorRow=14
+TopLine=1
+LeftChar=1
+Open=0
+Top=0
+[Editor_19]
+CursorCol=12
+CursorRow=3
+TopLine=3
+LeftChar=1
+Open=0
+Top=0
+[Editor_11]
+CursorCol=8
+CursorRow=44
+TopLine=31
+LeftChar=1
+Open=0
+Top=0
+[Editor_3]
+CursorCol=1
+CursorRow=268
+TopLine=243
+LeftChar=1
+Open=1
+Top=0
+[Editor_15]
+CursorCol=15
+CursorRow=7
+TopLine=1
+LeftChar=1
+Open=1
+Top=0
+[Editor_8]
+CursorCol=1
+CursorRow=69
+TopLine=33
+LeftChar=1
+Open=0
+Top=0
+[Editor_16]
+CursorCol=2
+CursorRow=25
+TopLine=1
+LeftChar=1
+Open=0
+Top=0
+[Editor_0]
+CursorCol=39
+CursorRow=212
+TopLine=184
+LeftChar=1
+Open=1
+Top=0
+[Editors]
+Focused=7
+Order=5,0,10,17,3,6,7,22,21,20,15
+[Editor_1]
+Open=0
+Top=0
+CursorCol=21
+CursorRow=63
+TopLine=30
+LeftChar=1
+[Editor_2]
+Open=0
+Top=0
+CursorCol=7
+CursorRow=83
+TopLine=50
+LeftChar=1
+[Editor_4]
+Open=0
+Top=0
+CursorCol=19
+CursorRow=21
+TopLine=21
+LeftChar=1
+[Editor_6]
+Open=1
+Top=0
+CursorCol=1
+CursorRow=577
+TopLine=556
+LeftChar=1
+[Editor_9]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+[Editor_12]
+Open=0
+Top=0
+CursorCol=6
+CursorRow=99
+TopLine=91
+LeftChar=1
+[Editor_13]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=204
+TopLine=170
+LeftChar=1
+[Editor_14]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=290
+TopLine=256
+LeftChar=1
+[Editor_17]
+Open=1
+Top=0
+CursorCol=68
+CursorRow=133
+TopLine=112
+LeftChar=1
+[Editor_20]
+Open=1
+Top=0
+CursorCol=46
+CursorRow=195
+TopLine=163
+LeftChar=1
+[Editor_21]
+Open=1
+Top=0
+CursorCol=2
+CursorRow=58
+TopLine=57
+LeftChar=1
+[Editor_22]
+Open=1
+Top=0
+CursorCol=32
+CursorRow=160
+TopLine=129
+LeftChar=1
+[Editor_23]
+Open=0
+Top=0
+CursorCol=2
+CursorRow=6
+TopLine=1
+LeftChar=1
+[Editor_24]
+CursorCol=1
+CursorRow=56
+TopLine=25
+LeftChar=1
+Open=0
+Top=0
+[Editor_25]
+Open=0
+Top=0
+CursorCol=18
+CursorRow=8
+TopLine=1
+LeftChar=1
diff --git a/assdraw/src/Makefile.win b/assdraw/src/Makefile.win
new file mode 100644
index 000000000..aa45a440e
--- /dev/null
+++ b/assdraw/src/Makefile.win
@@ -0,0 +1,69 @@
+# Project: ASSDraw
+# Compiler: Default GCC compiler
+# Compiler Type: MingW 3
+# Makefile created by wxDev-C++ 6.10.2 on 20/01/08 23:46
+
+CPP       = g++.exe
+CC        = gcc.exe
+WINDRES   = windres.exe
+OBJ       = ../Default\ Profile/assdraw.o ../Default\ Profile/cmd.o ../Default\ Profile/engine.o ../Default\ Profile/dlgctrl.o ../Default\ Profile/canvas.o ../Default\ Profile/AGGWindow.o ../Default\ Profile/agg_vcgen_bcspline.o ../Default\ Profile/agg_bcspline.o ../Default\ Profile/library.o ../Default\ Profile/settings.o ../Default\ Profile/assdraw_settings.o ../Default\ Profile/canvas_mouse.o ../Default\ Profile/ASSDraw3_private.res
+LINKOBJ   = "../Default Profile/assdraw.o" "../Default Profile/cmd.o" "../Default Profile/engine.o" "../Default Profile/dlgctrl.o" "../Default Profile/canvas.o" "../Default Profile/AGGWindow.o" "../Default Profile/agg_vcgen_bcspline.o" "../Default Profile/agg_bcspline.o" "../Default Profile/library.o" "../Default Profile/settings.o" "../Default Profile/assdraw_settings.o" "../Default Profile/canvas_mouse.o" "../Default Profile/ASSDraw3_private.res"
+LIBS      = -L"D:/Program Files/Dev-Cpp/Lib" -L"E:/DEV/agg-2.5" -L"E:/DEV/wxTreeMultiCtrl" -lwxmsw28_propgrid -mwindows -lwxmsw28 -lwxmsw28_gl -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregex -lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwinspool -lwinmm -lshell32 -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lwsock32 -lodbc32 -lopengl32 -lagg  -s 
+INCS      = -I"include" -I"E:/DEV" -I"E:/DEV/agg-2.5/include" -I"E:/DEV/wxTreeMultiCtrl/include"
+CXXINCS   = -I"D:/Program Files/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"D:/Program Files/Dev-Cpp/include/c++/3.4.2/backward" -I"D:/Program Files/Dev-Cpp/include/c++/3.4.2/mingw32" -I"D:/Program Files/Dev-Cpp/include/c++/3.4.2" -I"D:/Program Files/Dev-Cpp/include" -I"D:/Program Files/Dev-Cpp/" -I"D:/Program Files/Dev-Cpp/include/common/wx/msw" -I"D:/Program Files/Dev-Cpp/include/common/wx/generic" -I"D:/Program Files/Dev-Cpp/include/common/wx/fl" -I"D:/Program Files/Dev-Cpp/include/common/wx/gizmos" -I"D:/Program Files/Dev-Cpp/include/common/wx/html" -I"D:/Program Files/Dev-Cpp/include/common/wx/mmedia" -I"D:/Program Files/Dev-Cpp/include/common/wx/net" -I"D:/Program Files/Dev-Cpp/include/common/wx/ogl" -I"D:/Program Files/Dev-Cpp/include/common/wx/plot" -I"D:/Program Files/Dev-Cpp/include/common/wx/protocol" -I"D:/Program Files/Dev-Cpp/include/common/wx/stc" -I"D:/Program Files/Dev-Cpp/include/common/wx/svg" -I"D:/Program Files/Dev-Cpp/include/common/wx/xml" -I"D:/Program Files/Dev-Cpp/include/common/wx/xrc" -I"D:/Program Files/Dev-Cpp/include/common/wx" -I"D:/Program Files/Dev-Cpp/include/common" -I"E:/dev/ACE-5.5" -I"E:/DEV" -I"E:/DEV/agg-2.5/include" -I"E:/DEV/wxTreeMultiCtrl/include"
+RCINCS    = --include-dir "D:/PROGRA~1/Dev-Cpp/include/common"
+BIN       = ../Default\ Profile/ASSDraw3.exe
+DEFINES   = 
+CXXFLAGS  = $(CXXINCS) $(DEFINES) -D__WXMSW__ -DNO_GCC_PRAGMA -fno-rtti -fno-exceptions  -Wno-deprecated   -fexpensive-optimizations -O3
+CFLAGS    = $(INCS) $(DEFINES)   -fexpensive-optimizations -O3
+GPROF     = gprof.exe
+RM        = rm -f
+LINK      = g++.exe
+
+.PHONY: all all-before all-after clean clean-custom
+all: all-before $(BIN) all-after
+
+clean: clean-custom
+	$(RM) $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+	$(LINK) $(LINKOBJ) -o "..\Default Profile\ASSDraw3.exe" $(LIBS)
+
+../Default\ Profile/assdraw.o: $(GLOBALDEPS) assdraw.cpp assdraw.hpp _common.hpp enums.hpp include_once.hpp
+	$(CPP) -c assdraw.cpp -o "../Default Profile/assdraw.o" $(CXXFLAGS)
+
+../Default\ Profile/cmd.o: $(GLOBALDEPS) cmd.cpp
+	$(CPP) -c cmd.cpp -o "../Default Profile/cmd.o" $(CXXFLAGS)
+
+../Default\ Profile/engine.o: $(GLOBALDEPS) engine.cpp
+	$(CPP) -c engine.cpp -o "../Default Profile/engine.o" $(CXXFLAGS)
+
+../Default\ Profile/dlgctrl.o: $(GLOBALDEPS) dlgctrl.cpp assdraw.hpp _common.hpp
+	$(CPP) -c dlgctrl.cpp -o "../Default Profile/dlgctrl.o" $(CXXFLAGS)
+
+../Default\ Profile/canvas.o: $(GLOBALDEPS) canvas.cpp assdraw.hpp _common.hpp cmd.hpp agghelper.hpp
+	$(CPP) -c canvas.cpp -o "../Default Profile/canvas.o" $(CXXFLAGS)
+
+../Default\ Profile/AGGWindow.o: $(GLOBALDEPS) wxAGG/AGGWindow.cpp wxAGG/AGGWindow.h wxAGG/PixelFormatConvertor.h
+	$(CPP) -c wxAGG/AGGWindow.cpp -o "../Default Profile/AGGWindow.o" $(CXXFLAGS)
+
+../Default\ Profile/agg_vcgen_bcspline.o: $(GLOBALDEPS) agg_vcgen_bcspline.cpp agg_vcgen_bcspline.h agg_bcspline.h
+	$(CPP) -c agg_vcgen_bcspline.cpp -o "../Default Profile/agg_vcgen_bcspline.o" $(CXXFLAGS)
+
+../Default\ Profile/agg_bcspline.o: $(GLOBALDEPS) agg_bcspline.cpp agg_bcspline.h
+	$(CPP) -c agg_bcspline.cpp -o "../Default Profile/agg_bcspline.o" $(CXXFLAGS)
+
+../Default\ Profile/library.o: $(GLOBALDEPS) library.cpp assdraw.hpp _common.hpp library.hpp engine.hpp _common.hpp wxAGG/AGGWindow.h wxAGG/PixelFormatConvertor.h agg_conv_bcspline.h agg_vcgen_bcspline.h agg_bcspline.h
+	$(CPP) -c library.cpp -o "../Default Profile/library.o" $(CXXFLAGS)
+
+../Default\ Profile/settings.o: $(GLOBALDEPS) settings.cpp assdraw.hpp _common.hpp settings.hpp _common.hpp
+	$(CPP) -c settings.cpp -o "../Default Profile/settings.o" $(CXXFLAGS)
+
+../Default\ Profile/assdraw_settings.o: $(GLOBALDEPS) assdraw_settings.cpp assdraw.hpp _common.hpp
+	$(CPP) -c assdraw_settings.cpp -o "../Default Profile/assdraw_settings.o" $(CXXFLAGS)
+
+../Default\ Profile/canvas_mouse.o: $(GLOBALDEPS) canvas_mouse.cpp canvas_mouse.hpp _common.hpp enums.hpp engine.hpp _common.hpp wxAGG/AGGWindow.h wxAGG/PixelFormatConvertor.h agg_conv_bcspline.h agg_vcgen_bcspline.h agg_bcspline.h canvas.hpp engine.hpp enums.hpp
+	$(CPP) -c canvas_mouse.cpp -o "../Default Profile/canvas_mouse.o" $(CXXFLAGS)
+
+../Default\ Profile/ASSDraw3_private.res: ../Default\ Profile/ASSDraw3_private.rc assdraw.rc 
+	$(WINDRES) --input-format=rc -o "../Default Profile/ASSDraw3_private.res" $(RCINCS) ../DEFAUL~1/ASSDRA~1.RC -O coff
diff --git a/assdraw/src/_common.hpp b/assdraw/src/_common.hpp
new file mode 100644
index 000000000..93c17f235
--- /dev/null
+++ b/assdraw/src/_common.hpp
@@ -0,0 +1,14 @@
+
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/wx.h"
+#endif
+
+#define TITLE wxT("ASSDraw3")
+
+#define __DPDS__ wxDefaultPosition, wxDefaultSize
diff --git a/assdraw/src/agg_bcspline.cpp b/assdraw/src/agg_bcspline.cpp
new file mode 100644
index 000000000..b06539dc2
--- /dev/null
+++ b/assdraw/src/agg_bcspline.cpp
@@ -0,0 +1,289 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+//          mcseemagg@yahoo.com
+//          http://antigrain.com
+// 
+// AGG is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+// 
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_bcspline.h"
+
+namespace agg
+{
+    //------------------------------------------------------------------------
+    bcspline::bcspline() :
+        m_max(0),
+        m_num(0),
+        m_x(0),
+        m_y(0),
+        m_last_idx(-1)
+    {
+    }
+
+    //------------------------------------------------------------------------
+    bcspline::bcspline(int num) :
+        m_max(0),
+        m_num(0),
+        m_x(0),
+        m_y(0),
+        m_last_idx(-1)
+    {
+        init(num);
+    }
+
+    //------------------------------------------------------------------------
+    bcspline::bcspline(int num, const double* x, const double* y) :
+        m_max(0),
+        m_num(0),
+        m_x(0),
+        m_y(0),
+        m_last_idx(-1)
+    {
+        init(num, x, y);
+    }
+
+    
+    //------------------------------------------------------------------------
+    void bcspline::init(int max)
+    {
+        if(max > 2 && max > m_max)
+        {
+            m_am.resize(max * 3);
+            m_max = max;
+            m_x   = &m_am[m_max];
+            m_y   = &m_am[m_max * 2];
+        }
+        m_num = 0;
+        m_last_idx = -1;
+    }
+
+
+    //------------------------------------------------------------------------
+    void bcspline::add_point(double x, double y)
+    {
+        if(m_num < m_max)
+        {
+            m_x[m_num] = x;
+            m_y[m_num] = y;
+            ++m_num;
+        }
+    }
+
+
+    //------------------------------------------------------------------------
+    void bcspline::prepare()
+    {
+        if(m_num > 2)
+        {
+            int i, k, n1;
+            double* temp; 
+            double* r; 
+            double* s;
+            double h, p, d, f, e;
+    
+            for(k = 0; k < m_num; k++) 
+            {
+                m_am[k] = 0.0;
+            }
+
+            n1 = 3 * m_num;
+
+            pod_array<double> al(n1);
+            temp = &al[0];
+
+            for(k = 0; k < n1; k++) 
+            {
+                temp[k] = 0.0;
+            }
+
+            r = temp + m_num;
+            s = temp + m_num * 2;
+
+            n1 = m_num - 1;
+            d = m_x[1] - m_x[0];
+            e = (m_y[1] - m_y[0]) / d;
+
+            for(k = 1; k < n1; k++) 
+            {
+                h     = d;
+                d     = m_x[k + 1] - m_x[k];
+                f     = e;
+                e     = (m_y[k + 1] - m_y[k]) / d;
+                al[k] = d / (d + h);
+                r[k]  = 1.0 - al[k];
+                s[k]  = 6.0 * (e - f) / (h + d);
+            }
+
+            for(k = 1; k < n1; k++) 
+            {
+                p = 1.0 / (r[k] * al[k - 1] + 2.0);
+                al[k] *= -p;
+                s[k] = (s[k] - r[k] * s[k - 1]) * p; 
+            }
+
+            m_am[n1]     = 0.0;
+            al[n1 - 1]   = s[n1 - 1];
+            m_am[n1 - 1] = al[n1 - 1];
+
+            for(k = n1 - 2, i = 0; i < m_num - 2; i++, k--) 
+            {
+                al[k]   = al[k] * al[k + 1] + s[k];
+                m_am[k] = al[k];
+            }
+        }
+        m_last_idx = -1;
+    }
+
+
+
+    //------------------------------------------------------------------------
+    void bcspline::init(int num, const double* x, const double* y)
+    {
+        if(num > 2)
+        {
+            init(num);
+            int i;
+            for(i = 0; i < num; i++)
+            {
+                add_point(*x++, *y++);
+            }
+            prepare();
+        }
+        m_last_idx = -1;
+    }
+
+
+    //------------------------------------------------------------------------
+    void bcspline::bsearch(int n, const double *x, double x0, int *i) 
+    {
+        int j = n - 1;
+        int k;
+          
+        for(*i = 0; (j - *i) > 1; ) 
+        {
+            if(x0 < x[k = (*i + j) >> 1]) j = k; 
+            else                         *i = k;
+        }
+    }
+
+
+
+    //------------------------------------------------------------------------
+    double bcspline::interpolation(double x, int i) const
+    {
+        int j = i + 1;
+        double d = m_x[i] - m_x[j];
+        double h = x - m_x[j];
+        double r = m_x[i] - x;
+        double p = d * d / 6.0;
+        return (m_am[j] * r * r * r + m_am[i] * h * h * h) / 6.0 / d +
+               ((m_y[j] - m_am[j] * p) * r + (m_y[i] - m_am[i] * p) * h) / d;
+    }
+
+
+    //------------------------------------------------------------------------
+    double bcspline::extrapolation_left(double x) const
+    {
+        double d = m_x[1] - m_x[0];
+        return (-d * m_am[1] / 6 + (m_y[1] - m_y[0]) / d) * 
+               (x - m_x[0]) + 
+               m_y[0];
+    }
+
+    //------------------------------------------------------------------------
+    double bcspline::extrapolation_right(double x) const
+    {
+        double d = m_x[m_num - 1] - m_x[m_num - 2];
+        return (d * m_am[m_num - 2] / 6 + (m_y[m_num - 1] - m_y[m_num - 2]) / d) * 
+               (x - m_x[m_num - 1]) + 
+               m_y[m_num - 1];
+    }
+
+    //------------------------------------------------------------------------
+    double bcspline::get(double x) const
+    {
+        if(m_num > 2)
+        {
+            int i;
+
+            // Extrapolation on the left
+            if(x < m_x[0]) return extrapolation_left(x);
+
+            // Extrapolation on the right
+            if(x >= m_x[m_num - 1]) return extrapolation_right(x);
+
+            // Interpolation
+            bsearch(m_num, m_x, x, &i);
+            return interpolation(x, i);
+        }
+        return 0.0;
+    }
+
+
+    //------------------------------------------------------------------------
+    double bcspline::get_stateful(double x) const
+    {
+        if(m_num > 2)
+        {
+            // Extrapolation on the left
+            if(x < m_x[0]) return extrapolation_left(x);
+
+            // Extrapolation on the right
+            if(x >= m_x[m_num - 1]) return extrapolation_right(x);
+
+            if(m_last_idx >= 0)
+            {
+                // Check if x is not in current range
+                if(x < m_x[m_last_idx] || x > m_x[m_last_idx + 1])
+                {
+                    // Check if x between next points (most probably)
+                    if(m_last_idx < m_num - 2 && 
+                       x >= m_x[m_last_idx + 1] &&
+                       x <= m_x[m_last_idx + 2])
+                    {
+                        ++m_last_idx;
+                    }
+                    else
+                    if(m_last_idx > 0 && 
+                       x >= m_x[m_last_idx - 1] && 
+                       x <= m_x[m_last_idx])
+                    {
+                        // x is between pevious points
+                        --m_last_idx;
+                    }
+                    else
+                    {
+                        // Else perform full search
+                        bsearch(m_num, m_x, x, &m_last_idx);
+                    }
+                }
+                return interpolation(x, m_last_idx);
+            }
+            else
+            {
+                // Interpolation
+                bsearch(m_num, m_x, x, &m_last_idx);
+                return interpolation(x, m_last_idx);
+            }
+        }
+        return 0.0;
+    }
+
+}
+
diff --git a/assdraw/src/agg_bcspline.h b/assdraw/src/agg_bcspline.h
new file mode 100644
index 000000000..05d236497
--- /dev/null
+++ b/assdraw/src/agg_bcspline.h
@@ -0,0 +1,81 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+//          mcseemagg@yahoo.com
+//          http://antigrain.com
+// 
+// AGG is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+// 
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_bcspline_INCLUDED
+#define AGG_bcspline_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+    //----------------------------------------------------------------bcspline
+    // A very simple class of Bi-cubic Spline interpolation.
+    // First call init(num, x[], y[]) where num - number of source points, 
+    // x, y - arrays of X and Y values respectively. Here Y must be a function 
+    // of X. It means that all the X-coordinates must be arranged in the ascending
+    // order. 
+    // Then call get(x) that calculates a value Y for the respective X. 
+    // The class supports extrapolation, i.e. you can call get(x) where x is
+    // outside the given with init() X-range. Extrapolation is a simple linear 
+    // function.
+    //
+    //  See Implementation agg_bcspline.cpp
+    //------------------------------------------------------------------------
+    class bcspline 
+    {
+    public:
+        bcspline();
+        bcspline(int num);
+        bcspline(int num, const double* x, const double* y);
+
+        void   init(int num);
+        void   add_point(double x, double y);
+        void   prepare();
+
+        void   init(int num, const double* x, const double* y);
+
+        double get(double x) const;
+        double get_stateful(double x) const;
+    
+    private:
+        bcspline(const bcspline&);
+        const bcspline& operator = (const bcspline&);
+
+        static void bsearch(int n, const double *x, double x0, int *i);
+        double extrapolation_left(double x) const;
+        double extrapolation_right(double x) const;
+        double interpolation(double x, int i) const;
+
+        int               m_max;
+        int               m_num;
+        double*           m_x;
+        double*           m_y;
+        pod_array<double> m_am;
+        mutable int       m_last_idx;
+    };
+
+
+}
+
+#endif
diff --git a/assdraw/src/agg_conv_bcspline.h b/assdraw/src/agg_conv_bcspline.h
new file mode 100644
index 000000000..3d40b9619
--- /dev/null
+++ b/assdraw/src/agg_conv_bcspline.h
@@ -0,0 +1,58 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+//          mcseemagg@yahoo.com
+//          http://antigrain.com
+// 
+// AGG is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+// 
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_conv_bcspline_INCLUDED
+#define AGG_conv_bcspline_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vcgen_bcspline.h"
+#include "agg_conv_adaptor_vcgen.h"
+
+
+namespace agg
+{
+
+    //---------------------------------------------------------conv_bcspline
+    template<class VertexSource> 
+    struct conv_bcspline : public conv_adaptor_vcgen<VertexSource, vcgen_bcspline>
+    {
+        typedef conv_adaptor_vcgen<VertexSource, vcgen_bcspline> base_type;
+
+        conv_bcspline(VertexSource& vs) : 
+            conv_adaptor_vcgen<VertexSource, vcgen_bcspline>(vs) {}
+
+        void   interpolation_step(double v) { base_type::generator().interpolation_step(v); }
+        double interpolation_step() const { return base_type::generator().interpolation_step(); }
+
+    private:
+        conv_bcspline(const conv_bcspline<VertexSource>&);
+        const conv_bcspline<VertexSource>& 
+            operator = (const conv_bcspline<VertexSource>&);
+    };
+
+}
+
+
+#endif
+
diff --git a/assdraw/src/agg_vcgen_bcspline.cpp b/assdraw/src/agg_vcgen_bcspline.cpp
new file mode 100644
index 000000000..3276ac1f8
--- /dev/null
+++ b/assdraw/src/agg_vcgen_bcspline.cpp
@@ -0,0 +1,203 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+//          mcseemagg@yahoo.com
+//          http://antigrain.com
+// 
+// AGG is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+// 
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_vcgen_bcspline.h"
+
+namespace agg
+{
+
+    //------------------------------------------------------------------------
+    vcgen_bcspline::vcgen_bcspline() :
+        m_src_vertices(),
+        m_spline_x(),
+        m_spline_y(),
+        m_interpolation_step(1.0/50.0),
+        m_closed(0),
+        m_status(initial),
+        m_src_vertex(0)
+    {
+    }
+
+
+    //------------------------------------------------------------------------
+    void vcgen_bcspline::remove_all()
+    {
+        m_src_vertices.remove_all();
+        m_closed = 0;
+        m_status = initial;
+        m_src_vertex = 0;
+    }
+
+
+    //------------------------------------------------------------------------
+    void vcgen_bcspline::add_vertex(double x, double y, unsigned cmd)
+    {
+        m_status = initial;
+        if(is_move_to(cmd))
+        {
+            m_src_vertices.modify_last(point_d(x, y));
+        }
+        else
+        {
+            if(is_vertex(cmd))
+            {
+                m_src_vertices.add(point_d(x, y));
+            }
+            else
+            {
+                m_closed = get_close_flag(cmd);
+            }
+        }
+    }
+
+
+    //------------------------------------------------------------------------
+    void vcgen_bcspline::rewind(unsigned)
+    {
+        m_cur_abscissa = 0.0;
+        m_max_abscissa = 0.0;
+        m_src_vertex = 0;
+        if(m_status == initial && m_src_vertices.size() > 2)
+        {
+            if(m_closed)
+            {
+                m_spline_x.init(m_src_vertices.size() + 8);
+                m_spline_y.init(m_src_vertices.size() + 8);
+                m_spline_x.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).x);
+                m_spline_y.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).y);
+                m_spline_x.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].x);
+                m_spline_y.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].y);
+                m_spline_x.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].x);
+                m_spline_y.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].y);
+                m_spline_x.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].x);
+                m_spline_y.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].y);
+            }
+            else
+            {
+                m_spline_x.init(m_src_vertices.size());
+                m_spline_y.init(m_src_vertices.size());
+            }
+            unsigned i;
+            for(i = 0; i < m_src_vertices.size(); i++)
+            {
+                double x = m_closed ? i + 4 : i;
+                m_spline_x.add_point(x, m_src_vertices[i].x);
+                m_spline_y.add_point(x, m_src_vertices[i].y);
+            }
+            m_cur_abscissa = 0.0;
+            m_max_abscissa = m_src_vertices.size() - 1;
+            if(m_closed)
+            {
+                m_cur_abscissa = 4.0;
+                m_max_abscissa += 5.0;
+                m_spline_x.add_point(m_src_vertices.size() + 4, m_src_vertices[0].x);
+                m_spline_y.add_point(m_src_vertices.size() + 4, m_src_vertices[0].y);
+                m_spline_x.add_point(m_src_vertices.size() + 5, m_src_vertices[1].x);
+                m_spline_y.add_point(m_src_vertices.size() + 5, m_src_vertices[1].y);
+                m_spline_x.add_point(m_src_vertices.size() + 6, m_src_vertices[2].x);
+                m_spline_y.add_point(m_src_vertices.size() + 6, m_src_vertices[2].y);
+                m_spline_x.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).x);
+                m_spline_y.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).y);
+            }
+            m_spline_x.prepare();
+            m_spline_y.prepare();
+        }
+        m_status = ready;
+    }
+
+
+
+
+
+
+    //------------------------------------------------------------------------
+    unsigned vcgen_bcspline::vertex(double* x, double* y)
+    {
+        unsigned cmd = path_cmd_line_to;
+        while(!is_stop(cmd))
+        {
+            switch(m_status)
+            {
+            case initial:
+                rewind(0);
+
+            case ready:
+                if(m_src_vertices.size() < 2)
+                {
+                    cmd = path_cmd_stop;
+                    break;
+                }
+
+                if(m_src_vertices.size() == 2)
+                {
+                    *x = m_src_vertices[m_src_vertex].x;
+                    *y = m_src_vertices[m_src_vertex].y;
+                    m_src_vertex++;
+                    if(m_src_vertex == 1) return path_cmd_move_to;
+                    if(m_src_vertex == 2) return path_cmd_line_to;
+                    cmd = path_cmd_stop;
+                    break;
+                }
+
+                cmd = path_cmd_move_to;
+                m_status = polygon;
+                m_src_vertex = 0;
+
+            case polygon:
+                if(m_cur_abscissa >= m_max_abscissa)
+                {
+                    if(m_closed)
+                    {
+                        m_status = end_poly;
+                        break;
+                    }
+                    else
+                    {
+                        *x = m_src_vertices[m_src_vertices.size() - 1].x;
+                        *y = m_src_vertices[m_src_vertices.size() - 1].y;
+                        m_status = end_poly;
+                        return path_cmd_line_to;
+                    }
+                }
+
+                *x = m_spline_x.get(m_cur_abscissa);
+                *y = m_spline_y.get(m_cur_abscissa);
+                m_src_vertex++;
+                m_cur_abscissa += m_interpolation_step;
+                return (m_src_vertex == 1) ? path_cmd_move_to : path_cmd_line_to;
+
+            case end_poly:
+                m_status = stop;
+                return path_cmd_end_poly | m_closed;
+
+            case stop:
+                return path_cmd_stop;
+            }
+        }
+        return cmd;
+    }
+
+
+}
+
diff --git a/assdraw/src/agg_vcgen_bcspline.h b/assdraw/src/agg_vcgen_bcspline.h
new file mode 100644
index 000000000..6f92d9942
--- /dev/null
+++ b/assdraw/src/agg_vcgen_bcspline.h
@@ -0,0 +1,83 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+//          mcseemagg@yahoo.com
+//          http://antigrain.com
+// 
+// AGG is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+// 
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_vcgen_bcspline_INCLUDED
+#define AGG_vcgen_bcspline_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_array.h"
+#include "agg_bcspline.h"
+
+
+namespace agg
+{
+
+    //==========================================================vcgen_bcspline
+    class vcgen_bcspline
+    {
+        enum status_e
+        {
+            initial,
+            ready,
+            polygon,
+            end_poly,
+            stop
+        };
+
+    public:
+        typedef pod_bvector<point_d, 6> vertex_storage;
+
+        vcgen_bcspline();
+
+        void interpolation_step(double v) { m_interpolation_step = v; }
+        double interpolation_step() const { return m_interpolation_step; }
+
+        // Vertex Generator Interface
+        void remove_all();
+        void add_vertex(double x, double y, unsigned cmd);
+
+        // Vertex Source Interface
+        void     rewind(unsigned path_id);
+        unsigned vertex(double* x, double* y);
+
+    private:
+        vcgen_bcspline(const vcgen_bcspline&);
+        const vcgen_bcspline& operator = (const vcgen_bcspline&);
+
+        vertex_storage m_src_vertices;
+        bcspline        m_spline_x;
+        bcspline        m_spline_y;
+        double         m_interpolation_step;
+        unsigned       m_closed;
+        status_e       m_status;
+        unsigned       m_src_vertex;
+        double         m_cur_abscissa;
+        double         m_max_abscissa;
+    };
+
+}
+
+
+#endif
+
diff --git a/assdraw/src/agghelper.hpp b/assdraw/src/agghelper.hpp
new file mode 100644
index 000000000..de0ce66fc
--- /dev/null
+++ b/assdraw/src/agghelper.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "agg_path_storage.h"
+
+class agghelper
+{
+public:
+	
+	static agg::path_storage RectanglePath(double left, double right, double top, double bottom)
+	{
+		agg::path_storage path;
+		path.move_to(left,top);
+		path.line_to(right,top);
+		path.line_to(right,bottom);
+		path.line_to(left,bottom);
+		path.line_to(left,top);
+		return path;
+	}
+	
+};
diff --git a/assdraw/src/assdraw.cpp b/assdraw/src/assdraw.cpp
new file mode 100644
index 000000000..132c01882
--- /dev/null
+++ b/assdraw/src/assdraw.cpp
@@ -0,0 +1,768 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        assdraw.cpp
+// Purpose:     ASSDraw main source file
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "assdraw.hpp"
+#include "enums.hpp"
+#include "include_once.hpp"
+#include <wx/clipbrd.h>
+#include <wx/wfstream.h>
+#include <wx/filename.h>
+#include <wx/dynlib.h>
+#include <wx/stdpaths.h>
+
+//DEFINE_EVENT_TYPE(wxEVT_SETTINGS_CHANGED)
+
+// initialize wxWidget to accept our App class
+IMPLEMENT_APP(ASSDrawApp)
+
+BEGIN_EVENT_TABLE(ASSDrawFrame, wxFrame)
+    EVT_TOOL(TB_CLEAR, ASSDrawFrame::OnSelect_Clear)
+    EVT_TOOL(TB_PREVIEW, ASSDrawFrame::OnSelect_Preview)
+    //EVT_TOOL(TB_EDITSRC, ASSDrawFrame::OnSelect_EditSrc)
+    EVT_TOOL(TB_TRANSFORM, ASSDrawFrame::OnSelect_Transform)
+    EVT_TOOL_RANGE(MODE_ARR, MODE_DEL, ASSDrawFrame::OnChoose_Mode)
+    EVT_TOOL_RANGE(DRAG_DWG, DRAG_BOTH, ASSDrawFrame::OnChoose_DragMode)
+    EVT_TOOL_RCLICKED(wxID_ANY, ASSDrawFrame::OnToolRClick)
+    EVT_COMMAND(wxID_ANY, wxEVT_SETTINGS_CHANGED, ASSDrawFrame::OnSettingsChanged) 
+    EVT_MENU_RANGE(MENU_TB_ALL, MENU_TB_BGIMG, ASSDrawFrame::OnChoose_TBarRClickMenu)
+#if wxUSE_MENUS
+    EVT_MENU(MENU_CLEAR, ASSDrawFrame::OnSelect_Clear)
+    EVT_MENU(MENU_PREVIEW, ASSDrawFrame::OnSelect_Preview)
+    EVT_MENU(MENU_TRANSFORM, ASSDrawFrame::OnSelect_Transform)
+    EVT_MENU(MENU_LIBRARY, ASSDrawFrame::OnSelect_Library)
+    EVT_MENU(MENU_SETTINGS, ASSDrawFrame::OnSelect_Settings)
+    EVT_MENU(MENU_RESETPERSPECTIVE, ASSDrawFrame::OnSelect_ResetPerspective)
+    EVT_MENU(MENU_HELP, ASSDrawFrame::OnSelect_Help)
+    EVT_MENU(wxID_ABOUT, ASSDrawFrame::OnSelect_About)
+    EVT_MENU(MENU_UNDO, ASSDrawFrame::OnSelect_Undo)
+    EVT_MENU(MENU_REDO, ASSDrawFrame::OnSelect_Redo)
+    EVT_MENU(MENU_PASTE, ASSDrawFrame::OnSelect_Paste)
+    EVT_MENU(MENU_BGIMG_REMOVE, ASSDrawFrame::OnSelect_RemoveBG)
+    EVT_MENU(MENU_BGIMG_ALPHA, ASSDrawFrame::OnSelect_AlphaBG)
+    EVT_MENU_RANGE(MODE_ARR, MODE_NUT_BILINEAR, ASSDrawFrame::OnChoose_Mode)
+    EVT_MENU_RANGE(DRAG_DWG, DRAG_BOTH, ASSDrawFrame::OnChoose_DragMode)
+    EVT_MENU_RANGE(MENU_REPOS_TOPLEFT, MENU_REPOS_BOTRIGHT, ASSDrawFrame::OnChoose_Recenter)
+    EVT_MENU_RANGE(MENU_REPOS_BGTOPLEFT, MENU_REPOS_BGBOTRIGHT, ASSDrawFrame::OnChoose_RecenterToBG)
+#endif //wxUSE_MENUS
+	EVT_CLOSE(ASSDrawFrame::OnClose)
+END_EVENT_TABLE()
+
+// ----------------------------------------------------------------------------
+// the application class: ASSDrawApp
+// ----------------------------------------------------------------------------
+
+// 'Main program' equivalent: the program execution "starts" here
+bool ASSDrawApp::OnInit()
+{
+    // create the main application window
+    ASSDrawFrame * assdrawframe = new ASSDrawFrame( this, TITLE, wxDefaultPosition, wxSize(640, 480) );
+	SetTopWindow(assdrawframe);
+    return TRUE;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// main frame: ASSDrawFrame
+// ----------------------------------------------------------------------------
+
+// constructor
+
+ASSDrawFrame::ASSDrawFrame( wxApp *app, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
+       : wxFrame(NULL, wxID_ANY, title, pos, size, style)
+{
+	m_app = app;
+    m_mgr.SetManagedWindow(this);
+    m_mgr.SetFlags(m_mgr.GetFlags() | wxAUI_MGR_ALLOW_ACTIVE_PANE);
+
+    // set the frame icon
+    SetIcon(wxICON(appico));
+    
+   	// Create status bar for the frame
+	#if wxUSE_STATUSBAR
+    CreateStatusBar(3);
+    int statwidths[] = { 64, -1, 64 };
+    GetStatusBar()->SetStatusWidths(3, statwidths);
+    SetStatusBarPane(1);
+	#endif // wxUSE_STATUSBAR
+	
+	InitializeDefaultSettings();
+	
+	// load config
+	configfile = wxFileName(::wxGetCwd(), _T("ASSDraw3.cfg")).GetFullPath();
+	if (!::wxFileExists(configfile))
+		configfile = wxFileName(wxStandardPaths::Get().GetUserConfigDir(), _T("ASSDraw3.cfg")).GetFullPath();
+
+	bool firsttime = !::wxFileExists(configfile);
+	if (firsttime) wxFileOutputStream(configfile).Close();
+	wxFileInputStream cfgf(configfile);
+	config = new wxFileConfig(cfgf);
+
+	// nullify transformdlg
+	transformdlg = NULL;
+
+	Maximize(true);
+	Show(true); // to get the right client size, must call Show() first
+
+	// config
+	LoadSettings();
+
+	// THE CANVAS
+    m_canvas = new ASSDrawCanvas( this , this );
+
+	// shapes library
+	shapelib = new ASSDrawShapeLibrary(this, this);
+
+	// source text ctrl
+	srctxtctrl = new ASSDrawSrcTxtCtrl(this, this);
+
+	// settings
+	/*
+	settingsdlg = NULL;
+	wxString settingsdllfile = wxFileName(::wxGetCwd(), "settings.dll").GetFullPath();
+
+	if (::wxFileExists(settingsdllfile))
+	{
+		wxDynamicLibrary settingsdll(settingsdllfile);
+		wxString symbol("CreateASSDrawSettingsDialogInstance");
+		if (settingsdll.IsLoaded() && settingsdll.HasSymbol(symbol)) 
+		{
+			typedef ASSDrawSettingsDialog* (*FuncType)(wxWindow*,ASSDrawFrame*,int);
+			FuncType func = (FuncType) settingsdll.GetSymbol(symbol);
+			//wxDYNLIB_FUNCTION(ASSDrawSettingsDialog, CreateASSDrawSettingsDialogInstance, settingsdll)
+			//ASSDrawSettingsDialog* test = func(NULL,this,971231);
+			//test->Reparent(this);
+			//test->Init();
+			//SetTitle(settingsdllfile);
+			//settingsdlg = func(NULL,this, 809131);
+			//settingsdlg->Init();
+			//m_mgr.AddPane(settingsdlg, wxAuiPaneInfo().Name(wxT("settings")).Caption(wxT("Settings")).Right().Layer(3).Position(0).CloseButton(true).BestSize(wxSize(240, 480)).MinSize(wxSize(200, 200)));
+		}
+	}
+	*/
+	
+	settingsdlg = new ASSDrawSettingsDialog(this, this);
+	settingsdlg->Init();
+	
+	SetMenus();
+	SetToolBars();
+	SetPanes();
+
+	// config
+
+	config->SetPath(_T("info"));
+	wxString version;
+	config->Read("version", &version);
+	config->SetPath("..");
+
+	default_perspective = m_mgr.SavePerspective(); // back up default perspective
+	config->SetPath("perspective");
+	wxString perspective;
+	if (config->Read("perspective", &perspective) && version == VERSION) m_mgr.LoadPerspective(perspective, false);
+	config->SetPath("..");
+
+	config->SetPath("library");
+	int n = 0;
+	config->Read("n", &n);
+	for (int i = 0; i < n; i++)
+	{
+		wxString libcmds;
+		config->Read(wxString::Format("%d",i), &libcmds);
+		shapelib->AddShapePreview(libcmds);		
+	}
+	config->SetPath("..");
+	
+    m_mgr.Update();
+	m_canvas->SetFocus();
+	m_canvas->Show();
+	
+	wxSize clientsize = m_canvas->GetClientSize();
+	m_canvas->ChangeZoomLevelTo(DEFAULT_SCALE, wxPoint(clientsize.x / 2, clientsize.y / 2));
+	m_canvas->MoveCanvasOriginTo(clientsize.x / 2, clientsize.y / 2);
+	UpdateASSCommandStringToSrcTxtCtrl(m_canvas->GenerateASS());
+
+	UpdateFrameUI();
+	ApplySettings();
+
+	#ifdef BETAVERSION
+	wxDateTime expire(15, wxDateTime::Dec, 2007, 0, 0, 0);
+	wxDateTime now = wxDateTime::Now();
+	if (now.IsLaterThan(expire))
+	{
+	 	wxMessageDialog expired(this, "Thank you for trying ASSDraw3. This beta version has expired. Please visit http://malakith.net/aegisub/index.php?topic=912.0 to get the latest release. Visit now?", wxT("Beta version"), wxYES_NO | wxICON_INFORMATION);
+	 	if (expired.ShowModal() == wxID_YES)
+			::wxLaunchDefaultBrowser(wxString("http://malakith.net/aegisub/index.php?topic=912.0"));
+		Close();
+	}
+	SetTitle(wxString::Format("%s beta %d (expires %s)", TITLE, BETAVERSION, expire.FormatDate().c_str()));
+	#endif
+
+	if (firsttime)
+		_About();
+	else if (!behaviors.nosplashscreen)
+		_About(3);
+
+	helpcontroller.SetParentWindow(this);
+	helpcontroller.Initialize(wxFileName(::wxGetCwd(), "ASSDraw3.chm").GetFullPath());
+}
+
+void ASSDrawFrame::SetToolBars()
+{
+    drawtbar = new wxToolBar(this, wxID_ANY, __DPDS__ , wxTB_FLAT | wxTB_TEXT | wxTB_NODIVIDER | wxTB_HORIZONTAL);
+	drawtbar->AddTool(TB_CLEAR, _T("Clear"), wxBITMAP(new_), wxNullBitmap, wxITEM_NORMAL, "", TIPS_CLEAR);
+    //tbar->AddTool(TB_EDITSRC, _T("Source"), wxBITMAP(src_), wxNullBitmap, wxITEM_NORMAL, "", TIPS_EDITSRC);
+    drawtbar->AddCheckTool(TB_PREVIEW, _T("Preview"), wxBITMAP(preview_), wxNullBitmap, "", TIPS_PREVIEW);
+    //drawtbar->AddTool(TB_TRANSFORM, _T("Transform"), wxBITMAP(rot_), wxNullBitmap, wxITEM_NORMAL, "", TIPS_TRANSFORM);
+	zoomslider = new wxSlider(drawtbar, TB_ZOOMSLIDER, 1000, 100, 5000, __DPDS__ );
+	//zoomslider->SetSize(280, zoomslider->GetSize().y);
+	zoomslider->Connect(wxEVT_SCROLL_LINEUP, wxScrollEventHandler(ASSDrawFrame::OnZoomSliderChanged), NULL, this);
+	zoomslider->Connect(wxEVT_SCROLL_LINEDOWN, wxScrollEventHandler(ASSDrawFrame::OnZoomSliderChanged), NULL, this);
+	zoomslider->Connect(wxEVT_SCROLL_PAGEUP, wxScrollEventHandler(ASSDrawFrame::OnZoomSliderChanged), NULL, this);
+	zoomslider->Connect(wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler(ASSDrawFrame::OnZoomSliderChanged), NULL, this);
+	zoomslider->Connect(wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler(ASSDrawFrame::OnZoomSliderChanged), NULL, this);
+	zoomslider->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(ASSDrawFrame::OnZoomSliderChanged), NULL, this);
+	drawtbar->AddControl(zoomslider);
+    drawtbar->Realize();
+
+    m_mgr.AddPane(drawtbar, wxAuiPaneInfo().Name(wxT("drawtbar")).Caption(TBNAME_DRAW).
+                  ToolbarPane().Top().Position(0).Dockable(true).LeftDockable(false).RightDockable(false));
+
+    modetbar = new wxToolBar(this, wxID_ANY, __DPDS__ , wxTB_FLAT | wxTB_TEXT | wxTB_NODIVIDER | wxTB_HORIZONTAL);
+    modetbar->AddRadioTool(MODE_ARR, _T("Drag"), wxBITMAP(arr_), wxNullBitmap, "", TIPS_ARR);
+    modetbar->AddRadioTool(MODE_M, _T("Move"), wxBITMAP(m_), wxNullBitmap, "", TIPS_M);
+    //modetbar->AddRadioTool(MODE_N, _T("Move*"), wxBITMAP(n_), wxNullBitmap, "", TIPS_N);
+    modetbar->AddRadioTool(MODE_L, _T("Line"), wxBITMAP(l_), wxNullBitmap, "", TIPS_L);
+    modetbar->AddRadioTool(MODE_B, _T("Bezier"), wxBITMAP(b_), wxNullBitmap, "", TIPS_B);
+    //modetbar->AddRadioTool(MODE_S, _T("Spline"), wxBITMAP(s_), wxNullBitmap, "", TIPS_S);
+    //modetbar->AddRadioTool(MODE_P, _T("Extend"), wxBITMAP(p_), wxNullBitmap, "", TIPS_P);
+    //modetbar->AddRadioTool(MODE_C, _T("Close"), wxBITMAP(c_), wxNullBitmap, "", TIPS_C);
+    modetbar->AddRadioTool(MODE_DEL, _T("Delete"), wxBITMAP(del_), wxNullBitmap, "", TIPS_DEL);
+    modetbar->AddRadioTool(MODE_SCALEROTATE, _T("Scale/Rotate"), wxBITMAP(sc_rot_), wxNullBitmap, "", TIPS_SCALEROTATE);
+    modetbar->AddRadioTool(MODE_NUT_BILINEAR, _T("Bilinear"), wxBITMAP(nut_), wxNullBitmap, "", TIPS_NUTB);
+    //modetbar->AddRadioTool(MODE_NUT_PERSPECTIVE, _T("NUT:P"), wxBITMAP(arr_), wxNullBitmap, "", "");
+    modetbar->Realize();
+
+    m_mgr.AddPane(modetbar, wxAuiPaneInfo().Name(wxT("modetbar")).Caption(TBNAME_MODE).
+                  ToolbarPane().Top().Position(1).Dockable(true).LeftDockable(false).RightDockable(false));
+
+    bgimgtbar = new wxToolBar(this, wxID_ANY, __DPDS__ , wxTB_FLAT | wxTB_TEXT | wxTB_NODIVIDER | wxTB_HORIZONTAL);
+	bgimgtbar->SetToolBitmapSize(wxSize(24,15));
+    bgimgtbar->AddCheckTool(DRAG_DWG, _T("Pan drawing"), wxBITMAP(pan_shp), wxNullBitmap, "", TIPS_DWG);
+    bgimgtbar->AddCheckTool(DRAG_BGIMG, _T("Pan background"), wxBITMAP(pan_bg), wxNullBitmap, "", TIPS_BGIMG);
+    //bgimgtbar->AddRadioTool(DRAG_BOTH, _T("Pan both"), wxBITMAP(pan_both), wxNullBitmap, "", TIPS_BOTH);
+    bgimgtbar->Realize();
+
+    m_mgr.AddPane(bgimgtbar, wxAuiPaneInfo().Name(wxT("bgimgtbar")).Caption(TBNAME_BGIMG).
+                  ToolbarPane().Top().Position(2).Dockable(true).LeftDockable(false).RightDockable(false));
+	
+}
+
+void ASSDrawFrame::SetMenus()
+{
+#if wxUSE_MENUS
+	drawMenu = new wxMenu;
+	drawMenu->Append(MENU_CLEAR, _T("&Clear\tCtrl+N"), TIPS_CLEAR);
+	//drawMenu->Append(MENU_EDITSRC, _T("&Source"), TIPS_EDITSRC);
+	drawMenu->Append(MENU_PREVIEW, _T("&Preview\tCtrl+P"), TIPS_PREVIEW, wxITEM_CHECK);
+	drawMenu->Append(MENU_TRANSFORM, _T("&Transform"), TIPS_TRANSFORM);
+	drawMenu->Append(MENU_PASTE, _T("&Paste\tCtrl+V"), TIPS_PASTE);
+	drawMenu->AppendSeparator();
+	drawMenu->Append(MENU_UNDO, _T("&Undo\tCtrl+Z"), TIPS_UNDO);
+	drawMenu->Append(MENU_REDO, _T("&Redo\tCtrl+Y"), TIPS_REDO);
+	drawMenu->Enable(MENU_UNDO, false);
+	drawMenu->Enable(MENU_REDO, false);
+
+	modeMenu = new wxMenu;
+	modeMenu->Append(MODE_ARR, _T("D&rag\tF1"), TIPS_ARR, wxITEM_RADIO);
+	modeMenu->Append(MODE_M, _T("Draw &M\tF2"), TIPS_M, wxITEM_RADIO);
+	modeMenu->Append(MODE_L, _T("Draw &L\tF3"), TIPS_L, wxITEM_RADIO);
+	modeMenu->Append(MODE_B, _T("Draw &B\tF4"), TIPS_B, wxITEM_RADIO);
+	modeMenu->Append(MODE_DEL, _T("&Delete\tF5"), TIPS_DEL, wxITEM_RADIO);
+	modeMenu->Append(MODE_SCALEROTATE, _T("&Scale/Rotate\tF6"), TIPS_NUTB, wxITEM_RADIO);
+	modeMenu->Append(MODE_NUT_BILINEAR, _T("&Bilinear transformation\tF7"), TIPS_SCALEROTATE, wxITEM_RADIO);
+
+	bgimgMenu = new wxMenu;
+	bgimgMenu->Append(DRAG_DWG, _T("Pan/Zoom &Drawing\tShift+F1"), TIPS_DWG, wxITEM_CHECK);
+	bgimgMenu->Append(DRAG_BGIMG, _T("Pan/Zoom Back&ground\tShift+F2"), TIPS_BGIMG, wxITEM_CHECK);
+	bgimgMenu->AppendSeparator();
+	bgimgMenu->Append(MENU_BGIMG_ALPHA, _T("Set background image opacity"), "");
+	wxMenu* reposbgMenu = new wxMenu;
+	reposbgMenu->Append( MENU_REPOS_BGTOPLEFT, "Top left\tCtrl+Shift+7" );
+	reposbgMenu->Append( MENU_REPOS_BGTOPRIGHT, "Top right\tCtrl+Shift+9" );
+	reposbgMenu->Append( MENU_REPOS_BGCENTER, "&Center\tCtrl+Shift+5" );
+	reposbgMenu->Append( MENU_REPOS_BGBOTLEFT, "Bottom left\tCtrl+Shift+1" );
+	reposbgMenu->Append( MENU_REPOS_BGBOTRIGHT, "Bottom right\tCtrl+Shift+3" );
+	bgimgMenu->Append(MENU_BGIMG_RECENTER, _T("Reposition [&0, 0]"), reposbgMenu);
+	bgimgMenu->Append(MENU_BGIMG_REMOVE, _T("Remove background\tShift+Del"), "");
+
+	wxMenu* reposMenu = new wxMenu;
+	reposMenu->Append( MENU_REPOS_TOPLEFT, "Top left\tCtrl+7" );
+	reposMenu->Append( MENU_REPOS_TOPRIGHT, "Top right\tCtrl+9" );
+	reposMenu->Append( MENU_REPOS_CENTER, "&Center\tCtrl+5" );
+	reposMenu->Append( MENU_REPOS_BOTLEFT, "Bottom left\tCtrl+1" );
+	reposMenu->Append( MENU_REPOS_BOTRIGHT, "Bottom right\tCtrl+3" );
+
+	tbarMenu = new wxMenu;
+	tbarMenu->AppendCheckItem(MENU_TB_DRAW, TBNAME_DRAW);
+	tbarMenu->AppendCheckItem(MENU_TB_MODE, TBNAME_MODE);
+	tbarMenu->AppendCheckItem(MENU_TB_BGIMG, TBNAME_BGIMG);
+	tbarMenu->AppendSeparator();
+	tbarMenu->Append(MENU_TB_ALL, "Show all");
+	tbarMenu->Append(MENU_TB_NONE, "Hide all");
+	tbarMenu->Append(MENU_TB_DOCK, "Dock all");
+	tbarMenu->Append(MENU_TB_UNDOCK, "Undock all");
+
+	viewMenu = new wxMenu;
+	viewMenu->Append(MENU_LIBRARY, _T("&Library"), TIPS_LIBRARY, wxITEM_CHECK);
+	if (settingsdlg)
+		viewMenu->Append(MENU_SETTINGS, _T("&Settings"), "", wxITEM_CHECK);
+	viewMenu->Append(MENU_TBAR, _T("&Toolbars"), tbarMenu);
+	viewMenu->Append(MENU_RECENTER, _T("Reposition [&0, 0]"), reposMenu);
+	viewMenu->AppendSeparator();
+	viewMenu->Append(MENU_RESETPERSPECTIVE, _T("&Reset workspace"));
+
+	wxMenu* helpMenu = new wxMenu;
+	helpMenu->Append(MENU_HELP, _T("&Manual"));
+	helpMenu->Append(wxID_ABOUT, _T("&About"));
+
+	wxMenuBar *menuBar = new wxMenuBar();
+	menuBar->Append(drawMenu, _T("&Canvas"));
+	menuBar->Append(modeMenu, _T("&Mode"));
+	menuBar->Append(bgimgMenu, _T("&Background"));
+	menuBar->Append(viewMenu, _T("&Workspace"));
+	menuBar->Append(helpMenu, _T("&Help"));
+
+
+	SetMenuBar(menuBar);
+#endif // wxUSE_MENUS
+}
+
+void ASSDrawFrame::SetPanes()
+{
+	m_mgr.AddPane(shapelib, wxAuiPaneInfo().Name(wxT("library")).Caption(wxT("Shapes Library")).
+                  Right().Layer(2).Position(0).CloseButton(true).BestSize(wxSize(120, 480)).MinSize(wxSize(100, 200)));
+
+	m_mgr.AddPane(m_canvas, wxAuiPaneInfo().Name(wxT("canvas")).CenterPane());
+
+	m_mgr.AddPane(srctxtctrl, wxAuiPaneInfo().Name(wxT("commands")).Caption(wxT("Drawing commands")).
+                  Bottom().Layer(1).CloseButton(false).BestSize(wxSize(320, 48)));
+	
+	if (settingsdlg)
+		m_mgr.AddPane(settingsdlg, wxAuiPaneInfo().Name(wxT("settings")).Caption(wxT("Settings")).
+                  Right().Layer(3).Position(0).CloseButton(true).BestSize(wxSize(240, 480)).MinSize(wxSize(200, 200)).Show(false));
+}
+
+ASSDrawFrame::~ASSDrawFrame()
+{
+	config->SetPath("info");
+	config->Write("assdraw3.exe", wxStandardPaths::Get().GetExecutablePath());
+	config->Write("version", VERSION);
+	config->SetPath("..");
+
+	SaveSettings();
+	
+	config->SetPath("perspective");
+	config->Write("perspective", m_mgr.SavePerspective());
+	config->SetPath("..");
+
+	config->DeleteGroup("library");
+	config->SetPath("library");
+	typedef std::vector< ASSDrawShapePreview *> PrevVec;
+	PrevVec shapes = shapelib->GetShapePreviews();
+	int n = shapes.size();
+	config->Write("n", n);
+	for (int i = 0; i < n; i++)
+		config->Write(wxString::Format("%d",i), shapes[i]->GenerateASS());
+	config->SetPath("..");
+
+	wxFileOutputStream cfgf(configfile);
+	config->Save(cfgf);
+	delete config;
+	
+	if (settingsdlg) settingsdlg->Destroy(); // we need this since wxPropertyGrid must be Clear()ed before deleting
+
+	m_mgr.UnInit();
+}
+
+void ASSDrawFrame::_Clear()
+{
+	wxMessageDialog msgb(this, _T("Clear the canvas and create a new drawing?"), 
+                  _T("Confirmation"), wxOK | wxCANCEL | wxICON_QUESTION );
+	if (msgb.ShowModal() == wxID_OK)
+	{
+		m_canvas->RefreshUndocmds();
+		m_canvas->AddUndo("Clear canvas");
+		m_canvas->ResetEngine(true);
+	    wxSize siz = m_canvas->GetClientSize();
+		m_canvas->ChangeZoomLevelTo(DEFAULT_SCALE, wxPoint(siz.x / 2, siz.y / 2));
+		m_canvas->MoveCanvasOriginTo(siz.x / 2, siz.y / 2);
+		UpdateUndoRedoMenu();
+		m_canvas->RefreshDisplay();
+	}
+}
+
+void ASSDrawFrame::_Preview()
+{
+	m_canvas->SetPreviewMode( !m_canvas->IsPreviewMode() );
+	UpdateFrameUI();
+	m_canvas->RefreshDisplay();
+}
+
+void ASSDrawFrame::_ToggleLibrary()
+{
+	m_mgr.GetPane(shapelib).Show(!m_mgr.GetPane(shapelib).IsShown());
+	m_mgr.Update();
+	UpdateFrameUI();
+}
+
+void ASSDrawFrame::_ToggleSettings()
+{
+	if (settingsdlg == NULL) return;
+	m_mgr.GetPane(settingsdlg).Show(!m_mgr.GetPane(settingsdlg).IsShown());
+	m_mgr.Update();
+	UpdateFrameUI();
+}
+
+void ASSDrawFrame::_ResetPerspective()
+{
+	m_mgr.LoadPerspective(default_perspective, false);
+	UpdateFrameUI();
+	m_mgr.Update();
+	DRAGMODE bck = m_canvas->GetDragMode();
+	if (m_canvas->HasBackgroundImage()) m_canvas->SetDragMode(DRAGMODE(true, true));
+	wxSize clientsize = m_canvas->GetClientSize();
+	m_canvas->ChangeZoomLevelTo(DEFAULT_SCALE, wxPoint(clientsize.x / 2, clientsize.y / 2));
+	m_canvas->MoveCanvasOriginTo(clientsize.x / 2, clientsize.y / 2);
+	m_canvas->SetDragMode(bck);
+	UpdateFrameUI();
+}
+
+void ASSDrawFrame::_Transform()
+{
+	if (transformdlg == NULL)
+		transformdlg = new ASSDrawTransformDlg( this );
+
+	if (transformdlg->ShowModal() == wxID_OK)
+	{
+		m_canvas->Transform(
+			transformdlg->xformvals.f1,
+			transformdlg->xformvals.f2,
+			transformdlg->xformvals.f3,
+			transformdlg->xformvals.f4,
+			transformdlg->xformvals.f5,
+			transformdlg->xformvals.f6,
+			transformdlg->xformvals.f7,
+			transformdlg->xformvals.f8 );
+		m_canvas->AddUndo("Transform");
+		m_canvas->RefreshDisplay();
+		UpdateUndoRedoMenu();
+	}
+}
+
+void ASSDrawFrame::_Paste()
+{
+	if (wxTheClipboard->Open())
+	{
+		if (wxTheClipboard->IsSupported( wxDF_BITMAP ))
+		{
+			wxBitmapDataObject data;
+			wxTheClipboard->GetData( data );
+			m_canvas->SetBackgroundImage( data.GetBitmap().ConvertToImage() );
+			//m_canvas->AskUserForBackgroundAlpha();
+		}
+		else if (wxTheClipboard->IsSupported( wxDF_TEXT ))
+		{
+			wxTextDataObject data;
+			wxTheClipboard->GetData( data );
+			UpdateASSCommandStringToSrcTxtCtrl( data.GetText() );
+		}
+		wxTheClipboard->Close();
+	}
+}
+
+void ASSDrawFrame::OnChoose_Recenter(wxCommandEvent& event)
+{
+	int x = 0, y = 0;
+	wxSize f = m_canvas->GetClientSize();
+
+	switch (event.GetId())
+	{
+	case MENU_REPOS_TOPLEFT: x = 0, y = 0; break;
+	case MENU_REPOS_TOPRIGHT: x = f.x, y = 0; break;
+	case MENU_REPOS_CENTER: x = f.x / 2, y = f.y / 2; break;
+	case MENU_REPOS_BOTLEFT: x = 0, y = f.y; break;
+	case MENU_REPOS_BOTRIGHT: x = f.x, y = f.y; break;
+	}
+
+	m_canvas->MoveCanvasOriginTo(x, y);
+	m_canvas->RefreshDisplay();
+}
+
+void ASSDrawFrame::OnChoose_RecenterToBG(wxCommandEvent& event)
+{
+	unsigned w, h;
+	wxRealPoint disp;
+	double scale;
+	if (m_canvas->GetBackgroundInfo(w, h, disp, scale))
+	{
+		int x = 0, y = 0;
+		int lx = (int)disp.x, ty = (int)disp.y;
+		int rx = lx + (int)(w * scale);
+		int by = ty + (int)(h * scale);
+		
+		switch (event.GetId())
+		{
+		case MENU_REPOS_BGTOPLEFT: x = lx, y = ty; break;
+		case MENU_REPOS_BGTOPRIGHT: x = rx, y = ty; break;
+		case MENU_REPOS_BGCENTER: x = (rx + lx) / 2, y = (by + ty) / 2; break;
+		case MENU_REPOS_BGBOTLEFT: x = lx, y = by; break;
+		case MENU_REPOS_BGBOTRIGHT: x = rx, y = by; break;
+		}
+	
+		m_canvas->MoveCanvasDrawing(x - m_canvas->GetOriginX(), y - m_canvas->GetOriginY());
+		m_canvas->RefreshDisplay();
+	}
+}
+
+void ASSDrawFrame::_Help()
+{
+	helpcontroller.DisplayContents();
+}
+
+void ASSDrawFrame::_About(unsigned timeout)
+{
+	ASSDrawAboutDlg *aboutdlg = new ASSDrawAboutDlg( this, timeout );
+	aboutdlg->ShowModal();
+	aboutdlg->Destroy();
+}
+
+void ASSDrawFrame::OnChoose_Mode(wxCommandEvent& event)
+{
+	m_canvas->SetDrawMode( (MODE) event.GetId() );
+	UpdateFrameUI();
+}
+
+void ASSDrawFrame::OnChoose_DragMode(wxCommandEvent& event)
+{
+	DRAGMODE dm = m_canvas->GetDragMode();
+	switch (event.GetId())
+	{
+		case DRAG_DWG: dm.drawing = !dm.drawing; break;
+		case DRAG_BGIMG: dm.bgimg = !dm.bgimg; break;
+	}
+	m_canvas->SetDragMode( dm );
+	UpdateFrameUI();
+}
+
+void ASSDrawFrame::OnZoomSliderChanged(wxScrollEvent &event)
+{
+	double zoom = (double) event.GetPosition() / 100.0;
+	m_canvas->ChangeZoomLevelTo(zoom, wxPoint((int) m_canvas->GetOriginX(), (int) m_canvas->GetOriginY()));
+}
+
+void ASSDrawFrame::OnToolRClick(wxCommandEvent& event)
+{
+	int id = event.GetId();
+	if (drawtbar->FindById(id) != NULL
+		|| modetbar->FindById(id) != NULL
+		|| bgimgtbar->FindById(id) != NULL)
+	{
+		PopupMenu(tbarMenu);
+	}
+}
+
+void ASSDrawFrame::OnChoose_TBarRClickMenu(wxCommandEvent& event)
+{
+	int id = event.GetId();
+	wxToolBar* tbar[3] = { drawtbar, modetbar, bgimgtbar };
+	bool tb[3] = { false, false, false };
+	bool show[2] = { false, true };
+	bool dock[2] = { false, true };
+	switch (id)
+	{
+	case MENU_TB_ALL: 
+		tb[0] = true, tb[1] = true, tb[2] = true;
+		show[0] = true, show[1] = true;
+		break;
+	case MENU_TB_NONE: 
+		tb[0] = true, tb[1] = true, tb[2] = true;
+		show[0] = true, show[1] = false;
+		break;
+	case MENU_TB_DOCK: 
+		tb[0] = true, tb[1] = true, tb[2] = true;
+		dock[0] = true, dock[1] = true;
+		break;
+	case MENU_TB_UNDOCK: 
+		tb[0] = true, tb[1] = true, tb[2] = true;
+		dock[0] = true, dock[1] = false;
+		break;
+	case MENU_TB_DRAW: 
+		tb[0] = true;
+		show[0] = true, show[1] = !m_mgr.GetPane(tbar[0]).IsShown();
+		break;
+	case MENU_TB_MODE: 
+		tb[1] = true;
+		show[0] = true, show[1] = !m_mgr.GetPane(tbar[1]).IsShown();
+		break;
+	case MENU_TB_BGIMG: 
+		tb[2] = true;
+		show[0] = true, show[1] = !m_mgr.GetPane(tbar[2]).IsShown();
+		break;
+	}
+	for (int i = 0; i < 3; i++)
+	{
+		if (tb[i])
+		{
+			if (show[0])
+				m_mgr.GetPane(tbar[i]).Show(show[1]);
+			if (dock[0])
+				if (dock[1])
+					m_mgr.GetPane(tbar[i]).Dock();
+				else
+					m_mgr.GetPane(tbar[i]).Float();
+		}
+	}
+	m_mgr.Update();
+	UpdateFrameUI();
+}
+
+void ASSDrawFrame::UpdateASSCommandStringFromSrcTxtCtrl(wxString cmds)
+{
+	m_canvas->ParseASS(cmds, true);
+	m_canvas->RefreshDisplay();
+}
+
+void ASSDrawFrame::UpdateASSCommandStringToSrcTxtCtrl(wxString cmd)
+{
+	if (behaviors.capitalizecmds)
+		cmd.UpperCase();
+	else
+		cmd.LowerCase();
+	srctxtctrl->ChangeValue(cmd);
+	//srctxtctrl->AppendText(cmd);
+}
+
+void ASSDrawFrame::UndoOrRedo(bool isundo)
+{
+	if (isundo)
+		m_canvas->Undo();
+	else
+		m_canvas->Redo();
+	UpdateUndoRedoMenu();
+	UpdateFrameUI();
+}
+
+void ASSDrawFrame::UpdateUndoRedoMenu()
+{
+	wxString nextUndo = m_canvas->GetTopUndo();
+	if (nextUndo.IsSameAs(""))
+	{
+		drawMenu->SetLabel(MENU_UNDO, "Undo\tCtrl+Z");
+		drawMenu->Enable(MENU_UNDO, false);
+	}
+	else
+	{
+		drawMenu->SetLabel(MENU_UNDO, wxString::Format("Undo: %s\tCtrl+Z", nextUndo.c_str()));
+		drawMenu->Enable(MENU_UNDO, true);
+	}
+	wxString nextRedo = m_canvas->GetTopRedo();
+	if (nextRedo.IsSameAs(""))
+	{
+		drawMenu->SetLabel(MENU_REDO, "Redo\tCtrl+Y");
+		drawMenu->Enable(MENU_REDO, false);
+	}
+	else
+	{
+		drawMenu->SetLabel(MENU_REDO, wxString::Format("Redo: %s\tCtrl+Y", nextRedo.c_str()));
+		drawMenu->Enable(MENU_REDO, true);
+	}
+}
+
+void ASSDrawFrame::UpdateFrameUI(unsigned level)
+{
+	bool hasbg = m_canvas->HasBackgroundImage();
+	int zoom = (int) round(m_canvas->GetScale() * 100.0);
+	switch (level)
+	{
+	case 0: // all
+		drawtbar->ToggleTool(TB_PREVIEW, m_canvas->IsPreviewMode());
+		modetbar->ToggleTool(m_canvas->GetDrawMode(), true);
+		#if wxUSE_MENUS
+		drawMenu->Check(MENU_PREVIEW, m_canvas->IsPreviewMode());
+		modeMenu->Check(m_canvas->GetDrawMode(), true);
+		#endif
+	case 2: // bgimg & toolbars
+		//bgimgtbar->ToggleTool(m_canvas->GetDragMode(), true);
+		bgimgtbar->ToggleTool(DRAG_DWG, m_canvas->GetDragMode().drawing);
+		bgimgtbar->ToggleTool(DRAG_BGIMG, m_canvas->GetDragMode().bgimg);
+		bgimgtbar->EnableTool(DRAG_BGIMG, hasbg);
+		//m_mgr.GetPane(bgimgtbar).Show(hasbg);
+		m_mgr.Update();
+		#if wxUSE_MENUS
+		viewMenu->Check(MENU_LIBRARY, m_mgr.GetPane(shapelib).IsShown());
+		if (settingsdlg)
+			viewMenu->Check(MENU_SETTINGS, m_mgr.GetPane(settingsdlg).IsShown());
+		//bgimgMenu->Check(m_canvas->GetDragMode(), true);
+		bgimgMenu->Check(DRAG_DWG, m_canvas->GetDragMode().drawing);
+		bgimgMenu->Check(DRAG_BGIMG, m_canvas->GetDragMode().bgimg);
+		bgimgMenu->Enable(DRAG_BGIMG, hasbg);
+		bgimgMenu->Enable(DRAG_BOTH, hasbg);
+		bgimgMenu->Enable(MENU_BGIMG_ALPHA, hasbg);
+		bgimgMenu->Enable(MENU_BGIMG_RECENTER, hasbg);
+		bgimgMenu->Enable(MENU_BGIMG_REMOVE, hasbg);
+		tbarMenu->Check(MENU_TB_DRAW, m_mgr.GetPane(drawtbar).IsShown());
+		tbarMenu->Check(MENU_TB_MODE, m_mgr.GetPane(modetbar).IsShown());
+		tbarMenu->Check(MENU_TB_BGIMG, m_mgr.GetPane(bgimgtbar).IsShown());
+		#endif
+	case 3:	// zoom slider
+		zoomslider->SetValue(zoom);
+		SetStatusText( wxString::Format("%d%%", zoom), 2 );
+		zoomslider->Enable(m_canvas->GetDragMode().drawing && m_canvas->CanZoom());
+	}
+}
+
+void ASSDrawFrame::OnClose(wxCloseEvent &event)
+{
+	if (event.CanVeto() && behaviors.confirmquit)
+	{
+		if (wxMessageDialog(this, wxT("Do you want to close ASSDraw3 now?"), wxT("Confirmation"), wxOK | wxCANCEL).ShowModal() == wxID_OK)
+			Destroy();	
+		else
+			event.Veto();
+	}
+	else
+		Destroy();	
+}
diff --git a/assdraw/src/assdraw.hpp b/assdraw/src/assdraw.hpp
new file mode 100644
index 000000000..065383d74
--- /dev/null
+++ b/assdraw/src/assdraw.hpp
@@ -0,0 +1,208 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        assdraw.hpp
+// Purpose:     header file for ASSDraw main source file; also includes
+//              declarations for all GUI elements (except wxRuler, which has
+//              its own header file)
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include "_common.hpp"
+
+#include <vector>
+#include <wx/aui/aui.h>
+#include <wx/fileconf.h>
+#include <wx/help.h>
+
+#include "canvas.hpp" // the canvas
+#include "dlgctrl.hpp" // custom dialogs & controls
+#include "settings.hpp" // settings property grid
+#include "library.hpp" // shape library
+
+//#define BETAVERSION 2
+#define VERSION "3.0 final"
+
+// this header file declares the following classes
+class ASSDrawApp;
+class ASSDrawFrame;
+class ASSDrawCanvas;
+
+class ASSDrawApp : public wxApp 
+{ 
+public:      
+    bool OnInit();
+};
+
+class ASSDrawFrame : public wxFrame
+{
+public:
+    // constructor
+    ASSDrawFrame(wxApp *app, const wxString& title, const wxPoint& pos, const wxSize& size = wxDefaultSize,
+            long style = wxDEFAULT_FRAME_STYLE);
+    virtual ~ASSDrawFrame();
+
+    // event handlers (these functions should _not_ be virtual)
+	// OnSelect_* for single items, OnChoose_* for many-choose-one items
+	void OnSelect_Clear(wxCommandEvent& WXUNUSED(event)) { _Clear(); }
+	void OnSelect_Preview(wxCommandEvent& WXUNUSED(event)) { _Preview(); }
+	void OnSelect_Transform(wxCommandEvent& WXUNUSED(event)) { _Transform(); }
+	void OnSelect_Library(wxCommandEvent& WXUNUSED(event)) { _ToggleLibrary(); }
+	void OnSelect_Settings(wxCommandEvent& WXUNUSED(event)) { _ToggleSettings(); }
+	void OnSelect_ResetPerspective(wxCommandEvent& WXUNUSED(event)) { _ResetPerspective(); }
+	void OnSelect_Help(wxCommandEvent& WXUNUSED(event)) { _Help(); }
+	void OnSelect_About(wxCommandEvent& WXUNUSED(event)) { _About(); }
+	void OnSelect_Undo(wxCommandEvent& WXUNUSED(event)) { UndoOrRedo( true ); }
+	void OnSelect_Redo(wxCommandEvent& WXUNUSED(event)) { UndoOrRedo( false ); }
+	void OnSelect_Paste(wxCommandEvent& WXUNUSED(event)) { _Paste(); }
+	void OnSelect_RemoveBG(wxCommandEvent& WXUNUSED(event)) { m_canvas->RemoveBackgroundImage(); }
+	void OnSelect_AlphaBG(wxCommandEvent& WXUNUSED(event)) { m_canvas->AskUserForBackgroundAlpha(); }
+	void OnChoose_Recenter(wxCommandEvent& event);
+	void OnChoose_RecenterToBG(wxCommandEvent& event);
+	void OnChoose_Mode(wxCommandEvent& event);
+	void OnChoose_DragMode(wxCommandEvent& event);
+	void OnZoomSliderChanged(wxScrollEvent &event);
+	void OnToolRClick(wxCommandEvent& event);
+	void OnChoose_TBarRClickMenu(wxCommandEvent& event);
+	void OnSettingsChanged(wxCommandEvent& event);
+	void OnClose(wxCloseEvent &event);
+
+	void UpdateASSCommandStringToSrcTxtCtrl(wxString cmds);
+	void UpdateASSCommandStringFromSrcTxtCtrl(wxString cmds);
+
+	void UndoOrRedo(bool isundo);
+	void UpdateUndoRedoMenu();
+
+    void _Clear();
+    void _Preview();
+    void _Transform();
+	void _ToggleLibrary();
+	void _ToggleSettings();
+    void _Help();
+    void _About(unsigned timeout = 0);
+    void _Paste();
+    void _ResetPerspective();
+
+	void UpdateFrameUI(unsigned level = 0);
+
+    // the canvas
+    wxApp *m_app;
+    ASSDrawCanvas* m_canvas;
+	wxAuiManager m_mgr;
+	wxString default_perspective;
+	ASSDrawSrcTxtCtrl* srctxtctrl;
+
+	// config
+	wxString configfile;
+	wxFileConfig *config;
+	
+    // toolbars
+    wxToolBar *drawtbar, *modetbar, *bgimgtbar;
+	
+	// zoom slider
+	wxSlider* zoomslider;
+	
+	//library
+	ASSDrawShapeLibrary *shapelib;
+	typedef std::vector< ASSDrawEngine* > DrawEngineVec;
+	DrawEngineVec libshapes;
+	
+	// menus
+#if wxUSE_MENUS
+    wxMenu *drawMenu;
+    wxMenu *modeMenu;
+    wxMenu *bgimgMenu;
+    wxMenu *viewMenu;
+    wxMenu *tbarMenu;
+#endif
+
+	// dialogs
+	ASSDrawTransformDlg* transformdlg;	
+	ASSDrawSettingsDialog* settingsdlg;
+	
+	// colors
+	struct
+	{
+		wxColour canvas_bg;
+		wxColour canvas_shape_normal;
+		wxColour canvas_shape_preview;
+		wxColour canvas_shape_outline;
+		wxColour canvas_shape_guideline;
+		wxColour canvas_shape_mainpoint;
+		wxColour canvas_shape_controlpoint;
+		wxColour canvas_shape_selectpoint;
+		wxColour library_shape;
+		wxColour library_libarea;
+		wxColour origin, ruler_h, ruler_v;
+	} colors;
+
+	struct
+	{
+		long canvas_shape_normal;
+		long canvas_shape_preview;
+		long canvas_shape_outline;
+		long canvas_shape_guideline;
+		long canvas_shape_mainpoint;
+		long canvas_shape_controlpoint;
+		long canvas_shape_selectpoint;
+	} alphas;
+
+	struct
+	{
+		long origincross;
+	} sizes;
+	
+	struct
+	{
+		bool capitalizecmds;
+		bool autoaskimgopac;
+		bool parse_spc;
+		bool nosplashscreen;
+		bool confirmquit;
+	} behaviors;
+	
+	void LoadSettings();
+	void SaveSettings();
+	void InitializeDefaultSettings();
+	void ApplySettings();
+	static void wxColourToAggRGBA(wxColour &colour, agg::rgba &rgba);
+	static void wxColourSetAlpha(wxColour &colour, long alpha);
+
+protected:
+	virtual void SetToolBars();
+	virtual void SetMenus();
+	virtual void SetPanes();
+	DECLARE_EVENT_TABLE()
+	
+	wxHelpController helpcontroller;
+
+};
diff --git a/assdraw/src/assdraw.rc b/assdraw/src/assdraw.rc
new file mode 100644
index 000000000..1ee736c0d
--- /dev/null
+++ b/assdraw/src/assdraw.rc
@@ -0,0 +1,101 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+APPICO                  ICON                    "../tsukasa.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+ASSDRAW3_               BITMAP                  "../bitmaps/assdraw3.bmp"
+NEW_                    BITMAP                  "../bitmaps/new_.bmp"
+SRC_                    BITMAP                  "../bitmaps/src_.bmp"
+PREVIEW_                BITMAP                  "../bitmaps/preview_.bmp"
+ARR_                    BITMAP                  "../bitmaps/arr_.bmp"
+M_                      BITMAP                  "../bitmaps/m_.bmp"
+N_                      BITMAP                  "../bitmaps/n_.bmp"
+L_                      BITMAP                  "../bitmaps/l_.bmp"
+B_                      BITMAP                  "../bitmaps/b_.bmp"
+S_                      BITMAP                  "../bitmaps/s_.bmp"
+P_                      BITMAP                  "../bitmaps/p_.bmp"
+C_                      BITMAP                  "../bitmaps/c_.bmp"
+DEL_                    BITMAP                  "../bitmaps/del_.bmp"
+NUT_                    BITMAP                  "../bitmaps/nut_.bmp"
+SC_ROT_                 BITMAP                  "../bitmaps/sc_rot_.bmp"
+ROT_                    BITMAP                  "../bitmaps/rot_.bmp"
+HELP_                   BITMAP                  "../bitmaps/help_.bmp"
+TRANSFORM               BITMAP                  "../bitmaps/transform.bmp"
+PAN_SHP                 BITMAP                  "../bitmaps/pan_shp.bmp"
+PAN_BG                  BITMAP                  "../bitmaps/pan_bg.bmp"
+//PAN_BOTH                BITMAP                  "../bitmaps/pan_both.bmp"
+ADD                     BITMAP                  "../bitmaps/add_.bmp"
+CHECK                   BITMAP                  "../bitmaps/check_.bmp"
+UNCHECK                 BITMAP                  "../bitmaps/uncheck_.bmp"
+DELCROSS                BITMAP                  "../bitmaps/del_cross.bmp"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/assdraw/src/assdraw_settings.cpp b/assdraw/src/assdraw_settings.cpp
new file mode 100644
index 000000000..860cdcd18
--- /dev/null
+++ b/assdraw/src/assdraw_settings.cpp
@@ -0,0 +1,190 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "assdraw.hpp"
+
+void ASSDrawFrame::InitializeDefaultSettings()
+{
+	colors.canvas_bg = wxColour(0xFF, 0xFF, 0xFF);
+	colors.canvas_shape_normal = wxColour(0x0, 0x0, 0xFF, 0x99);
+	colors.canvas_shape_preview = wxColour(0x0, 0x0, 0xFF);
+	colors.canvas_shape_outline = wxColour(0x0, 0x0, 0x0);
+	colors.canvas_shape_guideline = wxColour(0x66, 0x66, 0x66);
+	colors.canvas_shape_mainpoint = wxColour(0xFF, 0x0, 0x0, 0xCC);
+	colors.canvas_shape_controlpoint = wxColour(0x0, 0xFF, 0x0, 0xCC);
+	colors.canvas_shape_selectpoint = wxColour(0x0, 0x0, 0xCC);
+	colors.library_shape = wxColour(0x0, 0x66, 0x99);
+	colors.library_libarea = wxColour(0xFF, 0xFF, 0x99);
+	colors.origin = wxColour(0xFF, 0x0, 0x0);
+	colors.ruler_h = wxColour(0x0, 0x0, 0x66);
+	colors.ruler_v = wxColour(0x66, 0x0, 0x0);
+
+	alphas.canvas_shape_normal = 128;
+	alphas.canvas_shape_preview = 255;
+	alphas.canvas_shape_outline = 255;
+	alphas.canvas_shape_guideline = 255;
+	alphas.canvas_shape_mainpoint = 128;
+	alphas.canvas_shape_controlpoint = 128;
+	alphas.canvas_shape_selectpoint = 255;
+
+	sizes.origincross = 2;
+
+	behaviors.capitalizecmds = false;
+	behaviors.autoaskimgopac = true;
+	behaviors.parse_spc = false;
+	behaviors.nosplashscreen = false;
+	behaviors.confirmquit = true;
+}
+
+void ASSDrawFrame::ApplySettings()
+{
+	wxColourSetAlpha(colors.canvas_shape_normal, alphas.canvas_shape_normal);
+	wxColourSetAlpha(colors.canvas_shape_preview, alphas.canvas_shape_preview);
+	wxColourSetAlpha(colors.canvas_shape_outline, alphas.canvas_shape_outline);
+	wxColourSetAlpha(colors.canvas_shape_guideline, alphas.canvas_shape_guideline);
+	wxColourSetAlpha(colors.canvas_shape_mainpoint, alphas.canvas_shape_mainpoint);
+	wxColourSetAlpha(colors.canvas_shape_controlpoint, alphas.canvas_shape_controlpoint);
+	wxColourSetAlpha(colors.canvas_shape_selectpoint, alphas.canvas_shape_selectpoint);
+
+	wxColourToAggRGBA(colors.canvas_shape_normal, m_canvas->rgba_shape_normal);
+	wxColourToAggRGBA(colors.canvas_shape_preview, m_canvas->rgba_shape);
+	wxColourToAggRGBA(colors.canvas_shape_outline, m_canvas->rgba_outline);
+	wxColourToAggRGBA(colors.canvas_shape_guideline, m_canvas->rgba_guideline);
+	wxColourToAggRGBA(colors.canvas_shape_mainpoint, m_canvas->rgba_mainpoint);
+	wxColourToAggRGBA(colors.canvas_shape_controlpoint, m_canvas->rgba_controlpoint);
+	wxColourToAggRGBA(colors.canvas_shape_selectpoint, m_canvas->rgba_selectpoint);
+	wxColourToAggRGBA(colors.origin, m_canvas->rgba_origin);
+	wxColourToAggRGBA(colors.ruler_h, m_canvas->rgba_ruler_h);
+	wxColourToAggRGBA(colors.ruler_v, m_canvas->rgba_ruler_v);
+
+	m_canvas->color_bg.r = colors.canvas_bg.Red();
+	m_canvas->color_bg.g = colors.canvas_bg.Green();
+	m_canvas->color_bg.b = colors.canvas_bg.Blue();
+	m_canvas->color_bg.a = colors.canvas_bg.Alpha();
+	m_canvas->PrepareBackgroundBitmap(-1.0);
+	m_canvas->Refresh();
+
+	shapelib->libarea->SetBackgroundColour(colors.library_libarea);
+	typedef std::vector< ASSDrawShapePreview *> PrevVec;
+	PrevVec shapes = shapelib->GetShapePreviews();
+	int n = shapes.size();
+	for (int i = 0; i < n; i++)
+		wxColourToAggRGBA(colors.library_shape, shapes[i]->rgba_shape);
+	shapelib->libarea->Refresh();
+	
+	m_canvas->SetDrawCmdSet(wxT(behaviors.parse_spc? "m n l b s p c _":"m n l b _"));
+
+	UpdateASSCommandStringToSrcTxtCtrl(m_canvas->GenerateASS());
+}
+
+void ASSDrawFrame::wxColourToAggRGBA(wxColour &colour, agg::rgba &rgba)
+{
+	rgba.r = (double) colour.Red() / 255.0;
+	rgba.g = (double) colour.Green() / 255.0;
+	rgba.b = (double) colour.Blue() / 255.0;
+	rgba.a = (double) colour.Alpha() / 255.0;
+}
+
+void ASSDrawFrame::wxColourSetAlpha(wxColour &colour, long alpha)
+{
+	colour.Set(colour.Red(), colour.Green(), colour.Blue(), alpha);
+}
+
+void ASSDrawFrame::OnSettingsChanged(wxCommandEvent& event)
+{
+	ApplySettings();
+}
+
+void ASSDrawFrame::LoadSettings()
+{
+	#define CFGREADCOLOR(color) if (config->Read(#color, &tmpstr)) color.Set(tmpstr);
+	#define CFGREAD(var) config->Read(#var, &var);
+	config->SetPath("settings");
+	wxString tmpstr;
+	CFGREADCOLOR(colors.canvas_bg)
+	CFGREADCOLOR(colors.canvas_shape_normal)
+	CFGREADCOLOR(colors.canvas_shape_preview)
+	CFGREADCOLOR(colors.canvas_shape_controlpoint)
+	CFGREADCOLOR(colors.canvas_shape_guideline)
+	CFGREADCOLOR(colors.canvas_shape_mainpoint)
+	CFGREADCOLOR(colors.canvas_shape_outline)
+	CFGREADCOLOR(colors.canvas_shape_selectpoint)
+	CFGREADCOLOR(colors.library_libarea)
+	CFGREADCOLOR(colors.library_shape)
+	CFGREADCOLOR(colors.origin)
+	CFGREADCOLOR(colors.ruler_h)
+	CFGREADCOLOR(colors.ruler_v)
+	CFGREAD(alphas.canvas_shape_normal)
+	CFGREAD(alphas.canvas_shape_preview)
+	CFGREAD(alphas.canvas_shape_controlpoint)
+	CFGREAD(alphas.canvas_shape_guideline)
+	CFGREAD(alphas.canvas_shape_mainpoint)
+	CFGREAD(alphas.canvas_shape_outline)
+	CFGREAD(alphas.canvas_shape_selectpoint)
+	CFGREAD(sizes.origincross)
+	CFGREAD(behaviors.autoaskimgopac)
+	CFGREAD(behaviors.capitalizecmds)
+	CFGREAD(behaviors.parse_spc)
+	CFGREAD(behaviors.nosplashscreen)
+	CFGREAD(behaviors.confirmquit)
+	config->SetPath("..");
+}
+
+void ASSDrawFrame::SaveSettings()
+{
+	#define CFGWRITE(var) config->Write(#var, var);
+	#define CFGWRITECOLOR(color) config->Write(#color, color.GetAsString(wxC2S_HTML_SYNTAX));
+	config->SetPath("settings");
+	CFGWRITECOLOR(colors.canvas_bg)
+	CFGWRITECOLOR(colors.canvas_shape_normal)
+	CFGWRITECOLOR(colors.canvas_shape_preview)
+	CFGWRITECOLOR(colors.canvas_shape_controlpoint)
+	CFGWRITECOLOR(colors.canvas_shape_guideline)
+	CFGWRITECOLOR(colors.canvas_shape_mainpoint)
+	CFGWRITECOLOR(colors.canvas_shape_outline)
+	CFGWRITECOLOR(colors.canvas_shape_selectpoint)
+	CFGWRITECOLOR(colors.library_libarea)
+	CFGWRITECOLOR(colors.library_shape)
+	CFGWRITECOLOR(colors.origin)
+	CFGWRITECOLOR(colors.ruler_h)
+	CFGWRITECOLOR(colors.ruler_v)
+	CFGWRITE(alphas.canvas_shape_normal)
+	CFGWRITE(alphas.canvas_shape_preview)
+	CFGWRITE(alphas.canvas_shape_controlpoint)
+	CFGWRITE(alphas.canvas_shape_guideline)
+	CFGWRITE(alphas.canvas_shape_mainpoint)
+	CFGWRITE(alphas.canvas_shape_outline)
+	CFGWRITE(alphas.canvas_shape_selectpoint)
+	CFGWRITE(sizes.origincross)
+	CFGWRITE(behaviors.autoaskimgopac)
+	CFGWRITE(behaviors.capitalizecmds)
+	CFGWRITE(behaviors.parse_spc)
+	CFGWRITE(behaviors.nosplashscreen)
+	CFGWRITE(behaviors.confirmquit)
+	config->SetPath("..");
+}
diff --git a/assdraw/src/bitmaps/Copy of assdraw3.bmp b/assdraw/src/bitmaps/Copy of assdraw3.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..4fe735e5bf1bc4002571d9e50ea67e9f68af2087
GIT binary patch
literal 86454
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

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/add_.bmp b/assdraw/src/bitmaps/add_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..5a87ed3fb61ecf967c3c6e8c688499cb34ba5e2d
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6usDb~!pFb>!XP#XAD|3?j6lWs&0}C-
z_&;+d95FC3&|f{Od(qv4EDLcPnw#N{M`OVKG6>ZpdkWdv$l`GKLwpS((foo{4MZh`
Kq=S0=ZUzAS45cyv

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/arr_.bmp b/assdraw/src/bitmaps/arr_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..34ec029d12add935038ec13030ba1ee9c85f6536
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<Ffbgz0iHg6%D}*&
zrKR=i)hirI5W;uv+?hFZCNnd$mX_Arw{H;=sH`_{-arH%J$j^}0diq`dj~`WE7{lA
zf8oM~J9qBPojaF-fk9kc{QC9lSXDv<`}+DlJw5mC-D_oK#lXN&TwDSX$3^z_^<TSw
zJu)(qfq{XQmG$V+qgSq6IdkR=9`#S3KD}`9A}cE^Ec`$;t|02`>;Lrm)BXGRPn|qD
zfBvHK@^S_ShI8l6;W7WupFeNkzTLKM8$|KhvuANBK5*bbUtj<K|Nnpf{0UKv$7F~h
z5cS)(ZL_hlA*dK){<Z7Z@w*vfGKB2w>t|qKxOnj*giDa@>+8RA<qAP%a0SnvJ%h7x
HF&G#CEa&Rn

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/arr_1.bmp b/assdraw/src/bitmaps/arr_1.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..14f71ee262bdbf90349b6a4192a7773ec0faf601
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6u=oWgFoi-KzyY2<eagVVprxht>eVY8
zN)W<#?%bI<b0#x0vzC_D+qZ8K5~!><Z{9!z9zA-bp#gGXdwT~&1S{Fs*MH%{g*$id
z%$+-zfq_9>T>Sd=>sVDn1pE5>Jv}}5?%iu;WyQe2P+VLB5ywUL_4Qx7emycWl7WGN
zm6i4A(W6(cTsd>*3?B7QpFX{C@ggfLD{>&>3ZlNg{!gDj-M@eT)X9_c=PxQRFK1w2
zICt(G9`pbF`SbSe+ilynK@^`odlr}C0|yTD_4WV%|NrODpAf}(OokW&QNL~5HX9oo
xf{G#LU%P%CzndW@L&(0qeg+1Hix)3KxCF_*zWys$t`JlPSMcoFGdLR;0|2D_>Ye}q

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/assdraw3.bmp b/assdraw/src/bitmaps/assdraw3.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..debaf3c8ba7af02954fce4a505d249fdac00f2f9
GIT binary patch
literal 120054
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

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/b_.bmp b/assdraw/src/bitmaps/b_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..3046a904840686fb8a5f1fded2d8b9e7cfa29e2c
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbgT3>aerc#OoR
z93+NI3rNn`7+Drm1ivgX>LF^7Nn|sT*~n_(Y-9y!Y=|0UK}-?+vc#x|s6i%?%{*}6
pz<&lIhzPP8I2$5`Ov2S83u0yeXAnY0Sk+((5^p|4FY)Rb7yxK^uG|0s

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/b_.cur b/assdraw/src/bitmaps/b_.cur
new file mode 100644
index 0000000000000000000000000000000000000000..117906dd9c265a87b372c16f74027af59e493fc1
GIT binary patch
literal 4286
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
Ogdalrpa1{=55fR7ps2Y3

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/c_.bmp b/assdraw/src/bitmaps/c_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..8a37dae867d6be4f4791b6912361795a637de096
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbgT1~5hf1kFQI
z3uWTb0##vb3{iu|g$N>(5Cv!=$Xqlwrg}65Xk5zG8^ip9W-^2eF(0l5jSEqOM#9y=
w8E6U)960cwK?qq8t`cq$vMi>0G+AWse+D6Bge--JjpiOaDj`zDt7l*U08`e^K>z>%

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/check_.bmp b/assdraw/src/bitmaps/check_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..41ca19aa3d69b56c0cb7a33245e35fea8559ac6b
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6usDb~!pFb>!XP#XAD|0pXlOWb;R=3)
z?2v|r1_uX+|G2@43s>-{XJBAJ(~3tuC=|dLSqm=pV1)<*t_8pP|NsBP^+2@XQ4djo
prUjRJxMBzcV$1*k|A|x&v4te{5R0&y?|>U%s&60!kmHwlHUJvX@yY-I

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/del_.bmp b/assdraw/src/bitmaps/del_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..034986fd0cd52f869f4e60611cb833efb6ad2f7b
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<Ffbf|fD@-39Uae{
zIn&nG#>2zI%geiV%XWwiR+5*Omj?{s3?3dHtSTXb%hzp`l$3n?_U+TBPw(Eni?A0W
zjX`GR6*M+B!qumwq=ZMsVyJ=&>^^+l(9rPq?b~qmd-m)R7Z+c-VKY<(Dm8K9#Gam>
zFJHdAef#$I?b~<n-o1SJa&~rhP-ys${fAK19@umESX+Dhw{PDd>KPaqAnK1FKQ1F9
zvtZdOH1!7#99X_)-QvZIA?oMPpAS(V8XB6NUx=yrz<~qD&Ry#5>%VZ}!rQlRV`5_N
z-o3kW<w_M*wH*fzV^x3Pz=5s1_f4BN4X)nE$f$SnbX<xL95`_N{N+hgr=2))A|@tg
z!GZ-wCZ-U@uv7r0A%YNc=YhlR9UYO8k#=@=Gv_ac2;w0jRxmIy7@L~oQHCtFar;hl
X3yb!ieq=#B>?5boo0}6boPhxVBHY_R

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/del_cross.bmp b/assdraw/src/bitmaps/del_cross.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..e6dc0957f5f7a9211784f97967b15aca428d45d2
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6usDb~!pFb>!XP#XA0P{C+VH<R;p6IM
z|B2Mymiu2q#6HdA<nBFKw6tXY+PEG?eEGcpijqD$>Xn^^DB=eW9N2f@zlX`ZLr2iX
zE2EzqtK|8bFW$WyMJmp9e?!_gOn06<^FPL6vzk(BhWB~6Y(vTydy{#`j-!|Wmpyj;
zf0)f?U9G0l@FzRA{?GBbWMVXZb|-el5M9TQ|BtlYYGN?a)NqQW*@9r3%@A=s<d(Jn
zt&OJJS+5DP-H1mSMC!=l|5-j4Y%G@An$B~wTv`_K2qKP^oZI=|!*RQ_{r1+h?}rZj
z@6P{kYrC~G7mNG%?)YC7{mQ|1ouk9{`lOF=)0$Ggy4!E=FG10=Z0i5Ym=|_d%U$ia
z&TdALI&k2?&JF*Ayf1WQ|A8B_bn<^!r@cO|hc_-oR}5FPs23r1{K)^Rm{)tYAVlEG
GFc|<JP48*|

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/help.bmp b/assdraw/src/bitmaps/help.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..d5636e9aa2cbf0489f307f7b3e7db32fc7264a68
GIT binary patch
literal 1318
zcmZ?rRbyoU12Yx|1`P%V1_1^J27U$x21W)Bu=ocC1_mK+2xedeOMt~07#hHcp`ii9
zVgQj14Gati4jf=OaOVKShf~WK+Pzd6dVSRyCIx6P%m~(Em=&VMFgsM6VR57`!_p{S
zh7~b-47<~e84hNdG91b_V>p>-&TzKenc-Zu2g8MWKZXlUK@3;>k{PZ~%4E1XqmbeD
zyh?^U3u+kduk2)au%?IM@usN^Pqxisc)EQy!;AgP7+xG$!SM3PT87uhH!{3AvxDK?
zg?$Vkt{!3dc=I&Fr(0(jzTCgW@b$?}hHuaAFnoV;pW(-=M-0C{ykhwM=`F*buOArx
z{`ku9_vd$pe}8^4{Qvit;s5{tP`{2+qaiT-L*T>j{|rkOEMRB=Wn_l`3?Rht|38Fc
z_zz-&^8`CPyD$=92l1_}tSl`p%*{-Vh1uEJm4t+ZBz3@CBVl%SNiJS4US2LmGgD(D
zePMQ4ZhkH+RepXhbz>uaU14@EetupqQGR}2F++V_Z7`qPN`jxCpG#j?TNBLZRj?A}
z=jYMY)>IQ_7v$&X<~C5}=M~Y`R8tmaSK{JT(J@is=TgvAQ&tdWXP4y?kdx-)lF<OU
zQiz?MT~$a(NJdRVP1xLA0mNq)*3;F}P*WB*SC9fZpIsQtl^0eJ2XkTm;{|g8Z0np~

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/help_.bmp b/assdraw/src/bitmaps/help_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..eac6f2e5eb678eafb65feadc64fcb829892980fa
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6usDbi;$~m~VGtXH4^RwZyxouyF7x1O
zJRkjL`1}ikJRkjrh@<I>@pgkNTmAn(95H<U1rk5=KgQb)uBErG3St^u*?#}X{r-^<
zE<}m}rlq&83S`3PUl3UciL4$X0@4N60x=vSh=+tYEXLantNQ)^k+XGu(6mGRj#d5l
zDNUGK7(V~PW&Y~_|1q^-Rlnaq@_lqF#3g9HhPdazfdj}+f~fgErRjZiDufNu3pX6D
wo&gr55M>Y&t{5KvkXY-jtAf}93TIeifUqIXK#pIC7KlX<jc6oX!GQw@0Cs8YPyhe`

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/l_.bmp b/assdraw/src/bitmaps/l_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..92af791d0f08bec6d5fa88807a2176ceecea60cc
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbgT3>aerc#OoR
z+?b$xJPOdHAm*b9;^B@E_5T@!Ab~)nf8pvOy6}+y8HA7#9+k*a#G4P%MZ9_j1^}t#
B;uQb@

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/m_.bmp b/assdraw/src/bitmaps/m_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..5e5b4c8610a1893cacce226dbc9b2b8dde127ea9
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbgT3>bp}#0+C&
zV>koOhKRsPuyT+x2m_)F!iK9sX27K&43g9zIB<YQ>LHGSm=9q?EJAiUgbkO4C_v*v
z)F6{^1#m%35x5kx1K@&K)&FM@f-4|~LA?6^3_{3=7{d=7I6%Dl5Ce%<&%gixQ7W=3

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/n_.bmp b/assdraw/src/bitmaps/n_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..47c4ad7f2be9cbeec5ff75e88ec98af4f8300adc
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbgT3>bp}vKe3j
zV`LFzHkvGiYivxEdbna*sD~JS;J^Vm1KHVdHe42y0at^}fGC5I5OHKSL<E_H$U;bn
zI5Ha|f=ohWkpl!Gf~@Aifdl^;gdifAvX~;s>LI%DkpCHkkP#l0$Wn0kAPeGQ6R)0u
F0RTimx@`ae

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/new_.bmp b/assdraw/src/bitmaps/new_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..3c8f88d4144db9ca9042c7b5b7ab92a552365c7c
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbgTF>uBPJUl!Y
z7#OB4T!LwNSy|bO7cc&!g7@#=CnO|DNl9U9S+Q~R<jIr2VSp7YR@B$mV`{nl<at(B
z*5=KdZ@|EnD_5>wy?WxriNwUj-rinJE$esh&CAQ1GG$6%Utc2_<mKhX$H#kkcvMza
zPMbCjs}?smw@;rweg6FU<HwKBpFh8S`}WzhXT!q6X3d&4bLLEQbMvL^HzIp~{qDVR
zE$`mFd-CMT_3PJ9ojO%eP%vxOteTpdtlYdkr_SQi^7{4b`}gl(xpL*ii4z3{1<RK&
zPft&uvup*j`U3|Jz-@uM>iqfh5G_-uP7RKTL{pEf1@5Y|XV0EEaUwrIKPxK>Q$0jW
QKwwZNHh@(<6$Kd>0B1h$HUIzs

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/nut_.bmp b/assdraw/src/bitmaps/nut_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..f76644e38be090e22b53f724db2c2b1c243c388d
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6usDb~!pFb>!XP#XA0PrOU%ov%d$Fu+
z2RnNM9_0{aDk@zP5^W(Nv-0zo+Sp9ORFAAI!7-;nh6kd?$!SV$?Mevyz<~qE%0fbB
z&7Qq^ZC_`rs_258lmiD2Y~H+ENT_A!&b`Z*Z!aud3b%Cj?9C7pme-Zn3p2E7i0|FC
z^T2@v<>kvgJf<BuaDbDu!Ow5T?Ae<eWw`2v86b-5g&81db!Rg~#K54hzkmIK0|yuw
z>LDT!1;}KVkqSg=?b@9}LM;$BTz#*#F0$f!VTScn`XOpkQx`@>&4sYx>gQ)A){8PD
zYuUX8>K8e=j)e=iBCFrNayha}2)oBZYxDfsvuAHsQR#vxhPZ#-q+W;uOtM8)G%9Lt
zYU)B{^_a?*)s(;$2nn^UT?-0QhzQ*M2M!$AzH)h!JTE*{4;(nq-@o3#pbw%FLL#d_
raNt0PzC7HU2M!$Y@R(L!z8s<wLJA4BFfi2PLc+q$J9qAdsDzLJ*dK3?

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/p_.bmp b/assdraw/src/bitmaps/p_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..67aeafa72c8792ba6eab9499c8424a228d02d06f
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbgT3>bp}@n(RP
z8xJ=15LZD+{BDD&K_l^KfvAKlK;y#2;S4kdXk555I0K>pjfBg>8UGoCAZ#?1#>Uv=
d0<IpS3lI69K?oV)QHd-?y!jAa#H(ju003)^&OrbG

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/pan_bg.bmp b/assdraw/src/bitmaps/pan_bg.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..0587ca30ea3908745c46d726ad9d92e2f170e9e5
GIT binary patch
literal 1134
zcmZ?r&0}Ez12YB&1`P%V1_=fR27U$x21YOoEX8nyj{%G!JO+jX2M#3Q1_ww12?+^U
zmE#h}su<!PtWt1u4lkXU;$?;l!S%w`!$lwrxcK3v6MnyceSXE%<1?FgO=?`;Tr{mT
zr8O<W+d?PB%M7BJ8221mI&sV5Y5#uz`gs59{f)CvE}vc$<9mF|s=~B5G;?r;G{mkW
zODDd0`f%N>u0LNteYkrmFWh}@SHs-CHeXXMG;<*8A#SU${|`ZMe;r*m>Hq)#k8WIA
zKeKaQXYJ7yGj^?BynFfFzqd}1X3lbuIsgCve|G2E%Ufq3J^B=udB!aC{Ds3;NHXWx
z^2z_f;OE!(Kfk_DD?aJ7;H^sOX>IR=B$)&8*Z=?je|`D*>&wU9>6a!Se&N6LeOm4=
zG;{EWGsHdr{{4j*_2}u>*-P*CPP_c(<ws<5;DHPYXJjsfeQfE(W6LKWTR!<Xm^`+8
a^5LZuA?WC;84xvSBs`AL#7X52xH$le70~zq

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/pan_both.bmp b/assdraw/src/bitmaps/pan_both.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..84eb52fd04e479f512e58564a8e3dfacf78243a4
GIT binary patch
literal 1134
zcmZ?r&0}Ez12YB&1`P%V1_=fR27U$x21YOoEX8nyj{%G!JO+jX2M#3Q1_y9}&C8dk
z^YU(3xDZ)BAt3>o3uogJ-?MXPsg~CKy1G&=tvx$;5>$`NoH`quh0V?X88%IbkDm}9
zPo6n_QBjjpQ~xt;f}m0@t+lgfLyW>@FQ)kH^70lB4~PkH67D<P!3+ww!%HWoc$uYm
znI)NPB#Q9EwZj>cQd9e)q9E}FaTtVMU;iJ1AnrN5bi(iVug|ZTnlCB{*Neu;6c&c)
z#beHqr4zR-p7!teug9kjR4B@#ned-sQ>m5~BmqF|g&38PkN|N^ef@uk_>rX(-#mS|
zZdTWyub-}LUX=oKRj`tDlB7_+oE+A0#x&>XvPu8{|9^Dj()yX5^Ezucc2ws{N#=+M
zPxE$7GEj!t4k7V}^U>uXbN>JT|Lo4Sm$%M7dh{tQ^Nd;O`3r}yq<EP@Ou!@|enA#L
zwtVt`F!=fP{m-xO(~3{}EO@I@dRp82AW7yx{Pq9;|6gA|{`&H<clxEthhO+FeV>-Q
zizIU(?)mrcFT|)vPruGydbfAl<u@-sl4j1*iN}^tKDK=FaWHvo`Q*b(CqmHCRWslr
F007sZuWA4Q

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/pan_shape.bmp b/assdraw/src/bitmaps/pan_shape.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..32ada0ae3d649175b6017150b02972a3e27c6735
GIT binary patch
literal 1434
zcmZ?royE!k24)Nl3>pj!3~~$%4EziX42%pCU~v#3#Ld6}!XP#X^YHM1C=ATQ!*hT#
zVDq1WfdQ)#XyW^J@9NZ(>$fxLwbWYE)q+(EnxG}IX0Pk-n&@Kopg7@Xg7;)kn|4i!
zMfquawr)W)4~0vt+0#Qjt_0aUC{BQ&I~gH!Q=(dxg=R+jZCkns#Yh;3fhe>0?cUX@
zEOak73Suyvyk8J|Il!`0Pi~@%8D>B^fy~B;N2mbI0SDj#0yh<naXrcv9#FeBtb=Gw
z0GSP89yoA-fq@~9;Xec+$K_N%r>mj%Xy##Z;Q=*0#AC;*6~vj{sv<JU!|F~(2&Q>h
zMXm(dOb_umK$N==95}G1tEE#<Zf;5xW~ieXe<vekdWc8AodMBiA2@Je-|k(D^3yu?
z<SqwTqL~NbLQHMflvq(;ap1rKzyIv)?9iw~r5G6*;qidX*tKEZ%t*gZJ-KTUP7os>
z6epmW3Q=G2A3{S&<oJV#;3BszT{PL#rr*xsdW`$@5D&OpQPh)ZHpGk#Qzvxl$wEQ^
ZB7#CvWHyRPm>d+dJv=-xRgf?89{|5>DA)i1

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/pan_shp.bmp b/assdraw/src/bitmaps/pan_shp.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..1b5da621bf7b9b8e2d29f51724c3a225d0230ab0
GIT binary patch
literal 1134
zcmZ?r&0}Ez12YB&1`P%V1_=fR27U$x21YOoEX8nyj{%G!JO+jX2M#3Q1_ww12?+^U
zmE#h}su<!PtWsFb*}QytIxp{rg$psYU{#OR{5?B&mTGCuud6H7(%Q3gCz?^jn^R|F
zv#`1Oe*BIJ@$nPl<1x*_71GEm`=X*IrKaAG-*G>F$K9B%rCM5RXU|4ffb5=xgoOI~
z{}6;MKD)fU#lr()2!y=my9~{D$m+40v%J5*+RW^3%vOjAaB@;=YF|_o+(`t@$&-@0
z?70xG9nQEBxGGavn0RxxtzBEBqH-&2J=}!*@jI>utSr^iLQVj<0vXwzYiG}{Ffh0t
zu<~Z`nt8RgjZRMaa&l<l40jmTGy|7iJ9~D%oLr8CM5B|_yxLm0I93L-8?Y)MQgFb{
F0RSQ1z)t`G

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/preview_.bmp b/assdraw/src/bitmaps/preview_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..b8b6fbe983d6abbfc6e7e77ef160f440575aaaff
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbfAaG<57#mmbp
zJUo2Yu3ZOUptQ8q!^6YX)wQm!4kiYoCr+GbZEd}H@#5UvTrV##kkEkxYuBzdHa6b9
zd-v9@TTM+(=gyrA5kGL?Ku}Q7v}w~I+$b<uzI=H=KtM}N3q)|rlqo(wJ`nbS0|z1_
zBfGo1;oO3Pg3!>={QP{l$ijsSt*x!$+}X2d+t}E^xoC`)D_2@rSj?I=3t1e^KxC=(
z^z`!ba%7PM2M+Asy&E$eAZmJhd+qJ*XV0Du;ljzCJ9paH*uXsw7e8>|KzDbyv$Jz(
zXy}?XYmmjOtE-W{i7a*Cz=7)OYBMvl<;$1D#ogT8rca*^=VCIty1JsHqaot+=g;@_
z^n|dH$^HBHH#9U96&0;sy}GNbD=aJwB0G2PTxVzJrAwDCSg>I6;>G*+?SqIfTei&3
z&aR@O!ok78$;oNSk|hxF0|yS|<>h&MdxwUG`uh4hIy$afx9-4!13f)Gv9YlS4jkCK
ucQ0HeCS$^c2^JO>TefTo2?^=!?8H=nDN<WoYiep578bUD|9)gy1_l5|d&FG;

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/rot_.bmp b/assdraw/src/bitmaps/rot_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..b2c14a9065c762907a37fa72a54187a778d283bb
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6usDbi;$~m~VGtXH50C|J96fbm=E9R@
zbw}eejzp&(iB3J9SAMQ<+O?hgG0nTWb@$2Ax}(vlM<S9yC=yJ9*~hbrFD+S(tmXEx
z)2GTCjz*`REUCRbfBCH=Cl4GraOcd$tE)GjsqZ)%n|?g2`1<Bua4nbSEj=2ad9tMT
z)}a${K?vjS#cOBV`i{n?pX-_o5jk++z?u5?qtU6C=PrSZATzFS*nT`U??i6d&0SEB
zoX9RY5|MOk?_p$RaQ40PS3nA)Qm!mo2@wQwBa$9oz5(GPlUEijKc1d{G&T*2;?mD|
zPK2nxv;PRPN(lSG`74)aFFuh~d^9foSYp=su1R+e96j66aWp#h>bzwTHE86+i`TBq
zU3?<D_(J!jdxwr6IB?+V!WG97GEbM)-9LT?O)-QE*0Kbm_`rb!56@gWQ`K}dI`wo}
z{q@DG9-g`YQHD%DzJ%htdwUO^u4qKWZ$#45>$j2BW3r!|yL@B8^0SqVN8>Y(#H3*=
HAX@|gcH;NY

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/s_.bmp b/assdraw/src/bitmaps/s_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..1e8afab554fc392c634052869b72aec8d0c3b80a
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<FfbgT7#O1h{N|ym
zh4S!dfvA8hK;y#2aWRNd4^e|m;xg^Pfdk0OAZ$E};p*|LL6$``6OD_k62gWkKqDbi
p$mD+pAvl+y;sXZ`AghOK#LD>3AcTyts=*W_-h7B&;?*-S004v|#8&_S

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/sc_rot_.bmp b/assdraw/src/bitmaps/sc_rot_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..546d7fdf176d709e65d428eb0f8a6c653d4dedf4
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6usDb~!pFb>!XP#XAHWTEY}l}N#*9S`
z4P6NdzGh~a3U_YYxNhdm#Z65!va))Eg8JRv=eWBsb#duYP^foy-oJl8M9bbidm1t`
zlQcAX-Q8!oyDxWl-{S6m(B1vGyZbRWx23A8yREG!ySr~$z8s?dz<~qFW@d{_O^<`s
zAd@RJG`5?YA9r_O;O@S%zaOH0$&w`r=H}}$6tCCUU$3tZ(Z0sreO_4^M14d=#I(xF
z#i;7Ho13rD(10jD?(V+R-F;GA+<^lJCQO)6P*AXG@#3jS>i5~%EmBfC=H>=hf6U#z
z!`*$~o;?vhHnY-|=B3Nms&ns#p#?HxM_gRsiXn_C?(UnHELo7H@P7)!|0xU`+!-#J
zGu#KG-Rj&BHOS;bclQ-NJ#h7hqZp2Y72h{!z^Z<oyZhYIQn>nSISf1Ts^8`AJ|Qj+
zuKr~`!x{|r2f%T+%-wyeqhp1Uk%zW6T>YPk3=7N|ZkRKiF=v>g&OO`Rz2Duv&D*=u
z+dIbEI>f=DEI)tEnl)2WRrZ#P&B{<J2sLn5Q%qGA*%`pl>MT*4kr5dH0u>b%D^{$4
m#MFTU2O|9)6a7t#!}L4iHKryhEXV?(NPowgni^zfaP<JEQ&Il_

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/src_.bmp b/assdraw/src/bitmaps/src_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..ae2e55e07d7146b4f94f9f94860a157264995cf9
GIT binary patch
literal 776
zcmZ?r<zQw212YB&1`P%V1_1^J27U$x21W)6u=ph=1_mK+2nGu<Ffbgz05BOWQpjrI
zdKnlP_U{L2g2=+fAzTQFtOleMj1L?*fGiGC2@(ANA8IB<!T$Z|Tr^w2=7H2eRQ~_Z
z05JjLFf_#wi{K_h^fE9&wV)}6%R)>>mPOVAQ3iKBvf&Wx;8GALK}d)oL@&g_Xy(H$
zg{XlW1<?rC0+EF)Mpg!4Llhtf3q&!*8OWAmnheqP|3AbGXdq+N0uh9&11Bv=5JAKt
YE`gJ9K}c93bKz>RGLX&3RKUOh0BTuCUH||9

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/transform.bmp b/assdraw/src/bitmaps/transform.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..8ae24e5adedc729b62762af2530d9e2792564817
GIT binary patch
literal 25144
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
QF@@cop!gfbLplT)031+Y&;S4c

literal 0
HcmV?d00001

diff --git a/assdraw/src/bitmaps/uncheck_.bmp b/assdraw/src/bitmaps/uncheck_.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..b600bebece5db6b7773a9cde2d0f3a9a7aa1ebae
GIT binary patch
literal 774
zcmZ?rWn*Rl12YB&1`P%V1_1^J27U$x21W)6usDb~!pFb>!XP#XAD|0pXlOWb;R=3)
o?2v|r1_uX+|G2@43s*+f;|`wx0}?(CxB;en8VCX8_$8hV0M7m}ng9R*

literal 0
HcmV?d00001

diff --git a/assdraw/src/canvas.cpp b/assdraw/src/canvas.cpp
new file mode 100644
index 000000000..ab8eadeca
--- /dev/null
+++ b/assdraw/src/canvas.cpp
@@ -0,0 +1,2057 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        canvas.cpp
+// Purpose:     implementations of ASSDraw main canvas class
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#include "assdraw.hpp"
+#include "cmd.hpp"
+#include "agg_gsv_text.h"
+#include "agg_ellipse.h"
+#include "agg_conv_dash.h"
+#include "agg_trans_bilinear.h"
+#include "agg_trans_perspective.h"
+
+#include "agghelper.hpp"
+#include <math.h>
+#include <wx/image.h>
+#include <wx/filename.h>
+
+// ----------------------------------------------------------------------------
+// the main drawing canvas: ASSDrawCanvas
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(ASSDrawCanvas, ASSDrawEngine)
+    EVT_MOTION (ASSDrawCanvas::OnMouseMove)
+    EVT_LEFT_UP(ASSDrawCanvas::OnMouseLeftUp)
+    EVT_LEFT_DOWN(ASSDrawCanvas::OnMouseLeftDown)
+    EVT_RIGHT_UP(ASSDrawCanvas::OnMouseRightUp)
+    EVT_RIGHT_DOWN(ASSDrawCanvas::OnMouseRightDown)
+    EVT_RIGHT_DCLICK(ASSDrawCanvas::OnMouseRightDClick)
+	EVT_MOUSEWHEEL(ASSDrawCanvas::OnMouseWheel)
+    EVT_KEY_DOWN(ASSDrawCanvas::CustomOnKeyDown)
+    EVT_KEY_UP(ASSDrawCanvas::CustomOnKeyUp)
+	EVT_MENU(MENU_DRC_LNTOBEZ, ASSDrawCanvas::OnSelect_ConvertLineToBezier)
+	EVT_MENU(MENU_DRC_BEZTOLN, ASSDrawCanvas::OnSelect_ConvertBezierToLine)
+	EVT_MENU(MENU_DRC_C1CONTBEZ, ASSDrawCanvas::OnSelect_C1ContinuityBezier)
+	EVT_MENU(MENU_DRC_MOVE00, ASSDrawCanvas::OnSelect_Move00Here)
+	EVT_MOUSE_CAPTURE_LOST(ASSDrawCanvas::CustomOnMouseCaptureLost)
+END_EVENT_TABLE()
+
+ASSDrawCanvas::ASSDrawCanvas(wxWindow *parent, ASSDrawFrame *frame, int extraflags)
+ : ASSDrawEngine( parent, extraflags )
+{
+	m_frame = frame;
+	preview_mode = false;
+    lastDrag_left = NULL;
+    lastDrag_right = NULL;
+    dragAnchor_left = NULL;
+    dragAnchor_right = NULL;
+    newcommand = NULL;
+    mousedownAt_point = NULL;
+    pointedAt_point = NULL;
+    draw_mode = MODE_ARR;
+
+    //drag_mode = DRAG_DWG;
+    dragOrigin = false;
+	hilite_cmd = NULL;
+	hilite_point = NULL;
+	capturemouse_left = false;
+	capturemouse_right = false;
+	//was_preview_mode = false;
+	bgimg.bgbmp = NULL;
+	bgimg.bgimg = NULL;
+	bgimg.alpha = 0.5;
+	rectbound2upd = -1, rectbound2upd2 = -1;
+	
+	rgba_shape_normal = agg::rgba(0,0,1,0.5);
+	rgba_outline = agg::rgba(0,0,0);
+	rgba_guideline = agg::rgba(0.5,0.5,0.5);
+	rgba_mainpoint = agg::rgba(1,0,0,0.75);
+	rgba_controlpoint = agg::rgba(0,1,0,0.75);
+	rgba_selectpoint = agg::rgba(0,0,1,0.75);
+	rgba_origin = agg::rgba(0,0,0);
+	rgba_ruler_h = agg::rgba(0,0,1);
+	rgba_ruler_v = agg::rgba(1,0,0);
+
+	wxFlexGridSizer* sizer = new wxFlexGridSizer(1, 1);
+    sizer->AddGrowableRow(0);
+    sizer->AddGrowableCol(0);
+    sizer->Add( this, 0, wxGROW|wxGROW, 5);
+    parent->SetSizer(sizer);
+
+	// for background image loading
+	::wxInitAllImageHandlers();
+	bgimg.bgbmp = NULL;
+	bgimg.bgimg = NULL;
+	// drag image background file
+	SetDropTarget(new ASSDrawFileDropTarget(this));
+	
+	hasStatusBar = m_frame->GetStatusBar() != NULL;
+
+	// cursor = crosshair
+	SetCursor( *wxCROSS_CURSOR );
+
+	bgimg.alpha_dlg = new wxDialog(this, wxID_ANY, wxString("Background image opacity"));
+	bgimg.alpha_slider = new wxSlider(bgimg.alpha_dlg, TB_BGALPHA_SLIDER, 50, 0, 100, __DPDS__ , wxSL_LABELS);
+	bgimg.alpha_slider->SetSize(280, bgimg.alpha_slider->GetSize().y);
+	bgimg.alpha_dlg->Fit();
+	bgimg.alpha_dlg->Show(false);
+	bgimg.alpha_slider->Connect(wxEVT_SCROLL_LINEUP, wxScrollEventHandler(ASSDrawCanvas::OnAlphaSliderChanged), NULL, this);
+	bgimg.alpha_slider->Connect(wxEVT_SCROLL_LINEDOWN, wxScrollEventHandler(ASSDrawCanvas::OnAlphaSliderChanged), NULL, this);
+	bgimg.alpha_slider->Connect(wxEVT_SCROLL_PAGEUP, wxScrollEventHandler(ASSDrawCanvas::OnAlphaSliderChanged), NULL, this);
+	bgimg.alpha_slider->Connect(wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler(ASSDrawCanvas::OnAlphaSliderChanged), NULL, this);
+	bgimg.alpha_slider->Connect(wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler(ASSDrawCanvas::OnAlphaSliderChanged), NULL, this);
+	bgimg.alpha_slider->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(ASSDrawCanvas::OnAlphaSliderChanged), NULL, this);
+	
+	RefreshUndocmds();
+
+}
+
+// Destructor
+ASSDrawCanvas::~ASSDrawCanvas()
+{
+	ASSDrawEngine::ResetEngine(false);
+	if (pointsys) delete pointsys;
+	if (bgimg.bgbmp) delete bgimg.bgbmp;
+	if (bgimg.bgimg) delete bgimg.bgimg;
+}
+
+void ASSDrawCanvas::ParseASS(wxString str, bool addundo)
+{
+	if (addundo)
+		AddUndo(wxT("Modify drawing commands"));
+
+	ASSDrawEngine::ParseASS(str);
+
+	RefreshUndocmds();
+}
+
+void ASSDrawCanvas::ResetEngine(bool addM)
+{
+	ClearPointsSelection();
+	SetHighlighted(NULL, NULL);
+	SetPreviewMode(false);
+	SetDrawMode(MODE_ARR);
+	ASSDrawEngine::ResetEngine(addM);
+	RefreshUndocmds();
+}
+
+void ASSDrawCanvas::SetPreviewMode(bool mode)
+{
+	//was_preview_mode = mode;
+	preview_mode = mode;
+	if (preview_mode)
+	{
+		if (mousedownAt_point != NULL)
+		{
+			mousedownAt_point->cmd_main->Init();
+			mousedownAt_point = NULL;
+		}
+
+		if (pointedAt_point != NULL)
+			pointedAt_point = NULL;
+
+		SetHighlighted( NULL, NULL );
+
+		RefreshDisplay();
+	}
+}
+
+// (Re)draw canvas
+void ASSDrawCanvas::RefreshDisplay() 
+{ 
+	ASSDrawEngine::RefreshDisplay();
+	wxString asscmds = GenerateASS();
+	if (oldasscmds != asscmds)
+	{
+		m_frame->UpdateASSCommandStringToSrcTxtCtrl(asscmds);
+		oldasscmds = asscmds;
+	}
+}
+
+void ASSDrawCanvas::SetDrawMode( MODE mode ) 
+{ 
+	draw_mode = mode; 
+
+	if (!selected_points.empty())
+		ClearPointsSelection();
+
+	RefreshDisplay();
+
+	if (IsTransformMode())
+	{
+		isshapetransformable = cmds.size() > 1;
+		
+		if (isshapetransformable)
+		{
+
+			// backup cmds
+			backupcmds.free_all();
+			for (DrawCmdList::iterator iterate = cmds.begin(); iterate != cmds.end(); iterate++)
+			{
+				DrawCmd* cmd = (*iterate);
+				for (PointList::iterator iterate2 = cmd->controlpoints.begin(); iterate2 != cmd->controlpoints.end(); iterate2++)
+				{
+					wxPoint pp = (*iterate2)->ToWxPoint();
+					backupcmds.move_to(pp.x, pp.y);
+				}
+				wxPoint pp = (*iterate)->m_point->ToWxPoint();
+				backupcmds.move_to(pp.x, pp.y);			
+			}
+	
+			// calculate bounding rectangle
+			agg::trans_affine mtx;
+			trans_path *rm, *rb;
+			agg::conv_curve<trans_path> *rc;
+			ConstructPathsAndCurves(mtx, rm, rb, rc);
+			rasterizer.reset();
+			rasterizer.add_path(*rc);
+			delete rm, rb, rc;
+		    int minx = rasterizer.min_x(), miny = rasterizer.min_y();
+		    int maxx = rasterizer.max_x(), maxy = rasterizer.max_y();
+		    
+		    rectbound[0] = wxRealPoint(minx, miny);
+		    rectbound[1] = wxRealPoint(maxx, miny);
+		    rectbound[2] = wxRealPoint(maxx, maxy);
+		    rectbound[3] = wxRealPoint(minx, maxy);
+		    for (int i = 0; i < 4; i++)
+		    	rectbound2[i] = rectbound[i];
+	
+		    rectbound2upd = -1;
+		    rectbound2upd2 = -1;
+		    
+		    backupowner = NONE;
+		    InitiateDraggingIfTransformMode();
+		    
+		    if (maxx - minx < 5 || maxy - miny < 5)
+		    	isshapetransformable = false;
+		}	    
+	}
+	
+	RefreshUndocmds();
+	m_frame->UpdateFrameUI();
+	
+}
+
+void ASSDrawCanvas::SetDragMode( DRAGMODE mode )
+{
+	drag_mode = mode;
+}
+
+bool ASSDrawCanvas::IsTransformMode()
+{ 
+	return draw_mode == MODE_NUT_BILINEAR || draw_mode == MODE_SCALEROTATE; 
+}
+
+bool ASSDrawCanvas::CanZoom()
+{
+	return !IsTransformMode() || !drag_mode.drawing;
+}
+
+bool ASSDrawCanvas::CanMove()
+{
+	return !IsTransformMode() || dragAnchor_left == NULL;
+}
+
+// Do the dragging
+void ASSDrawCanvas::OnMouseMove(wxMouseEvent &event)
+{
+	mouse_point = event.GetPosition();
+	int xx, yy, wx, wy;
+	xx = mouse_point.x; yy = mouse_point.y;
+	pointsys->FromWxPoint ( mouse_point, wx, wy );
+	if (event.Dragging())
+	{
+		if (IsTransformMode() && isshapetransformable && backupowner == LEFT)
+		{
+			// update bounding polygon
+			if (rectbound2upd > -1)
+			{
+				wxPoint diff = mouse_point - *dragAnchor_left;
+				wxRealPoint rdiff(diff.x, diff.y);
+				switch(draw_mode)
+				{
+				case MODE_NUT_BILINEAR:
+					if (rectbound2upd2 == -1) //only one vertex dragged
+						rectbound2[rectbound2upd].x = xx, rectbound2[rectbound2upd].y = yy;
+					else
+					{
+						rectbound2[rectbound2upd].x += diff.x, rectbound2[rectbound2upd].y += diff.y;
+						rectbound2[rectbound2upd2].x += diff.x, rectbound2[rectbound2upd2].y += diff.y;
+					}
+					undodesc = "Bilinear transform";
+					*dragAnchor_left = mouse_point;
+					break;
+				case MODE_SCALEROTATE:
+					if (rectbound2upd2 == -1) //only one vertex dragged
+					{
+						int adjacent[2] = { (rectbound2upd + 3) % 4, (rectbound2upd + 1) % 4 };
+						int opposite = (rectbound2upd + 2) % 4; 
+						wxRealPoint newpoint = backup[rectbound2upd] + rdiff;
+						//wxPoint newadjacent[2];
+						double nx, ny;
+						for (int i = 0; i < 2; i++)
+						{
+							bool isect = agg::calc_intersection(
+								backup[opposite].x, backup[opposite].y, 
+								backup[adjacent[i]].x, backup[adjacent[i]].y,
+								newpoint.x, newpoint.y,
+								backup[adjacent[i]].x + diff.x, backup[adjacent[i]].y + diff.y,
+								&nx, &ny);
+							if (isect && !(fabs(nx - backup[opposite].x) < 10 && fabs(ny - backup[opposite].y) < 10))
+								rectbound2[adjacent[i]] = wxRealPoint(nx, ny);
+						}
+						GetThe4thPoint(backup[opposite].x, backup[opposite].y, 
+							rectbound2[adjacent[0]].x, rectbound2[adjacent[0]].y,
+							rectbound2[adjacent[1]].x, rectbound2[adjacent[1]].y, 
+							&rectbound2[rectbound2upd].x, &rectbound2[rectbound2upd].y);
+						if (event.ShiftDown()) // shift down = maintain aspect ratio (damn so complicated)
+						{
+							// first create the guide points, which are basically backup points reoriented based on mouse position
+							wxRealPoint guide[4];
+							guide[opposite] = backup[opposite];
+							guide[adjacent[0]] = backup[adjacent[0]];
+							guide[adjacent[1]] = backup[adjacent[1]];
+							for (int i = 0; i < 2; i++)
+							{
+								if ((rectbound2[adjacent[i]].x < guide[opposite].x && guide[opposite].x < guide[adjacent[i]].x)
+									|| (rectbound2[adjacent[i]].x > guide[opposite].x && guide[opposite].x > guide[adjacent[i]].x)
+									|| (rectbound2[adjacent[i]].y < guide[opposite].y && guide[opposite].y < guide[adjacent[i]].y)
+									|| (rectbound2[adjacent[i]].y > guide[opposite].y && guide[opposite].y > guide[adjacent[i]].y))
+								{
+									guide[adjacent[i]] = guide[opposite] - (guide[adjacent[i]] - guide[opposite]);
+								}
+							}
+							guide[rectbound2upd] = guide[adjacent[0]] + (guide[adjacent[1]] - guide[opposite]);
+							// now we determine which rescaled sides have larger enlargement/shrinkage ratio ..
+							double ix[2], iy[2], dx[2], dy[2];
+							for (int i = 0; i < 2; i++)
+							{
+								agg::calc_intersection(guide[opposite].x, guide[opposite].y, guide[rectbound2upd].x, guide[rectbound2upd].y,
+									rectbound2[rectbound2upd].x, rectbound2[rectbound2upd].y,
+									rectbound2[adjacent[i]].x, rectbound2[adjacent[i]].y, &ix[i], &iy[i]);
+								dx[i] = ix[i] - guide[opposite].x;
+								dy[i] = iy[i] - guide[opposite].y;
+							}
+							// .. and modify the other sides to follow the ratio
+							for (int i = 0; i < 2; i++)
+							{
+								int j = (i + 1) % 2;
+								if (fabs(dx[i]) > fabs(dx[j]) || fabs(dy[i]) > fabs(dy[j]))
+								{
+									rectbound2[rectbound2upd].x = ix[i];
+									rectbound2[rectbound2upd].y = iy[i];
+									GetThe4thPoint(rectbound2[adjacent[i]].x, rectbound2[adjacent[i]].y,
+										guide[opposite].x, guide[opposite].y, ix[i], iy[i],
+										&rectbound2[adjacent[j]].x, &rectbound2[adjacent[j]].y);
+								}
+							}
+						}
+					}
+					else // an edge dragged (i.e. move 2 vertices in sync)
+					{
+						// it is guaranteed that rectbound2upd and rectbound2upd2 are in clockwise direction
+						// from the way they are detected in OnMouseLeftDown()
+						int toupd[2] = { rectbound2upd, rectbound2upd2 };
+						int adjacent[2] = { (rectbound2upd2 + 2) % 4, (rectbound2upd2 + 1) % 4 };
+						wxRealPoint vertexone = backup[toupd[0]] + rdiff, vertextwo = backup[toupd[1]] + rdiff;
+						double nx, ny;
+						for (int i = 0; i < 2; i++)
+						{
+							agg::calc_intersection(
+								rectbound2[adjacent[i]].x, rectbound2[adjacent[i]].y,
+								backup[toupd[i]].x, backup[toupd[i]].y,
+								vertexone.x, vertexone.y,
+								vertextwo.x, vertextwo.y,
+								&nx, &ny);
+							if (!(fabs(nx - backup[adjacent[i]].x) < 10 && fabs(ny - backup[adjacent[i]].y) < 10))
+								rectbound2[toupd[i]].x = (int) nx, rectbound2[toupd[i]].y = (int) ny;
+						}
+					}
+					UpdateTranformModeRectCenter();
+					//*dragAnchor_left = mouse_point;
+					undodesc = "Scale";
+					break;
+				}
+			
+				// update points
+				UpdateNonUniformTransformation();
+				RefreshDisplay();
+			}
+		}
+		else if (draw_mode != MODE_DEL)
+		{
+
+			// point left-dragged
+			if (mousedownAt_point != NULL && mousedownAt_point->isselected) 
+			{
+				if (!mousedownAt_point->IsAt( wx, wy ))
+				{
+					if (draw_mode == MODE_ARR) {
+						int movex = wx - mousedownAt_point->x(), movey = wy - mousedownAt_point->y();
+						PointSet::iterator iter = selected_points.begin();
+						for (; iter != selected_points.end(); iter++)			
+							(*iter)->setXY( (*iter)->x() + movex, (*iter)->y() + movey );
+					}
+					else
+						mousedownAt_point->setXY( wx, wy );
+	
+					EnforceC1Continuity (mousedownAt_point->cmd_main, mousedownAt_point);
+											
+					RefreshDisplay();
+					if (undodesc == "")
+					{
+						if (mousedownAt_point->type == MP)
+							undodesc = wxT("Drag point");
+						else
+							undodesc = wxT("Drag control point");
+					}
+				}
+			} 
+			// origin left-dragged
+			else if (dragOrigin) 
+			{
+				if (wx != 0 || wy != 0)
+				{
+					wxPoint wxp = pointsys->ToWxPoint ( wx, wy );
+					MovePoints(-wx, -wy);
+					pointsys->originx = wxp.x;
+					pointsys->originy = wxp.y;
+					RefreshDisplay();
+					undodesc = wxT("Move origin");
+				}          
+			}
+			else if (dragAnchor_left != NULL)
+			{
+				// handle left-dragging here
+				if (lastDrag_left && dragAnchor_left != lastDrag_left)
+			       delete lastDrag_left;
+				lastDrag_left = new wxPoint(xx, yy);
+				int ax = dragAnchor_left->x, ay = dragAnchor_left->y;
+				int sx = lastDrag_left->x, sy = lastDrag_left->y;
+				int lx, rx, ty, by;
+				if (ax > sx) lx = sx, rx = ax;
+				else lx = ax, rx = sx;
+				if (ay > sy) ty = sy, by = ay;
+				else ty = ay, by = sy;
+				SelectPointsWithin( lx, rx, ty, by, GetSelectMode(event) );
+				RefreshDisplay();
+			}
+		}
+
+		// right-dragged
+		if (dragAnchor_right != NULL)
+		{
+			if (draw_mode == MODE_SCALEROTATE)
+			{
+				if (backupowner == RIGHT)
+				{
+					double cx = rectcenter.x, cy = rectcenter.y; // center x,y
+					double diameter = sqrt(pow(rectbound2[0].x - rectbound2[2].x, 2) + pow(rectbound2[0].y - rectbound2[2].y, 2));
+					double radius = diameter / 2;
+					double old_dx = dragAnchor_right->x - cx, old_dy = dragAnchor_right->y - cy;
+					double new_dx = mouse_point.x - cx, new_dy = mouse_point.y - cy;
+					double old_angle = atan2(old_dy, old_dx);
+					double new_angle = atan2(new_dy, new_dx);
+					double delta = new_angle - old_angle;
+					for (int i = 0; i < 4; i++)
+					{
+						old_dx = backup[i].x - cx, old_dy = backup[i].y - cy;
+						old_angle = atan2(old_dy, old_dx);
+						new_angle = old_angle + delta;
+						new_dx = radius * cos(new_angle), new_dy = radius * sin(new_angle);
+						rectbound2[i].x = (int)(new_dx + cx), rectbound2[i].y = (int)(new_dy + cy);
+					}
+					UpdateNonUniformTransformation();
+					RefreshDisplay();
+					undodesc = "Rotate";
+				}
+			}
+			else if (CanMove()) 
+			{
+				MoveCanvas(xx - dragAnchor_right->x, yy - dragAnchor_right->y);
+				dragAnchor_right->x = xx;
+				dragAnchor_right->y = yy;
+				RefreshDisplay();
+			}
+		}		
+	}    
+	else if (!preview_mode)// not dragging and not preview mode
+    {
+		if (IsTransformMode())
+		{
+			int oldrectbound = rectbound2upd;
+			rectbound2upd = -1;
+			rectbound2upd2 = -1;
+			for (int i = 0; i < 4; i++)
+			{
+				if (abs((int)rectbound2[i].x - mouse_point.x) <= pointsys->scale
+					&& abs((int)rectbound2[i].y - mouse_point.y) <= pointsys->scale)
+						rectbound2upd = i;
+			}
+			for (int i = 0; rectbound2upd == -1 && i < 4; i++)
+			{
+				int j = (i+1) % 4;
+				wxRealPoint &pi = rectbound2[i], &pj = rectbound2[j];
+				double dy = fabs(pj.y - pi.y);
+				double dy3 = dy / 3;
+				double dx = fabs(pj.x - pi.x);
+				double dx3 = dx / 3;
+				double ix, iy;
+				bool intersect = false;
+				if (dy > dx)
+				{
+					intersect = agg::calc_intersection(
+						pi.x, pi.y, pj.x, pj.y,
+	                    mouse_point.x - pointsys->scale, mouse_point.y,
+						mouse_point.x + pointsys->scale, mouse_point.y, &ix, &iy);
+					intersect &= fabs(mouse_point.x - ix) <= pointsys->scale;
+					intersect &= (pj.y > pi.y? 
+						pj.y - dy3 > iy && iy > pi.y + dy3:
+						pj.y + dy3 < iy && iy < pi.y - dy3);
+				}
+				else
+				{
+					intersect = agg::calc_intersection(
+						pi.x, pi.y, pj.x, pj.y,
+	                    mouse_point.x, mouse_point.y - pointsys->scale,
+						mouse_point.x, mouse_point.y + pointsys->scale, &ix, &iy);
+					intersect &= fabs(mouse_point.y - iy) <= pointsys->scale;
+					intersect &= (pj.x > pi.x? 
+						pj.x - dx3 > ix && ix > pi.x + dx3:
+						pj.x + dx3 < ix && ix < pi.x - dx3);
+				}
+				if (intersect)
+				{
+					rectbound2upd = i;
+					rectbound2upd2 = j;
+				}
+			}
+			if (rectbound2upd != -1 || oldrectbound != -1)
+				RefreshDisplay();
+		}
+		else
+		{
+	         /* figure out if the mouse is pointing at a point of a command
+	            we need not do this for dragging since this same block has set
+	            the related variables before the user starts to hold the button
+	            (well, before you can drag something you have to move the pointer
+	            over that thing first, right?) and we don't want to mess with those 
+	            when it's dragging
+	         */
+	         
+			// check if mouse points on any control point first
+			Point* last_pointedAt_point = pointedAt_point;
+			ControlAt( wx, wy, pointedAt_point );
+	
+			// then check if mouse points on any m_points
+			// override any control point set to pointedAt_point above
+			DrawCmd* p = PointAt( wx, wy );
+			if (p != NULL)
+			{
+				pointedAt_point = p->m_point;
+			}
+	         
+			if (pointedAt_point != last_pointedAt_point)
+			{
+				if (pointedAt_point != NULL)
+					SetHighlighted( pointedAt_point->cmd_main, pointedAt_point );
+				else
+					SetHighlighted( NULL, NULL );
+				RefreshDisplay();
+			}
+		}
+	} // not dragging and preview mode = ignore all mouse movements
+
+	// we are not done yet?
+    // oh yeah, we need to set the status bar just for fun
+    if (hasStatusBar)
+	{
+        m_frame->SetStatusText( 
+            wxString::Format( wxT("%5d %5d"), (int)wx, (int)wy ), 0 );
+        if (pointedAt_point == NULL || 
+             (newcommand != NULL && !newcommand->initialized) )
+           m_frame->SetStatusText( wxT(""), 1 );
+        else
+           m_frame->SetStatusText( wxT(" ") + pointedAt_point->cmd_main->ToString().Upper(), 1 );
+	}
+
+}
+
+// End drag points
+void ASSDrawCanvas::OnMouseLeftUp(wxMouseEvent& event)
+{
+	ProcessOnMouseLeftUp();
+	event.Skip( true );
+}
+
+void ASSDrawCanvas::ProcessOnMouseLeftUp()
+{
+	if (!capturemouse_left) return;
+	
+	// draw mode
+	if (newcommand != NULL) 
+	{
+		newcommand->Init();
+		switch (newcommand->type)
+		{
+		case M:
+			undodesc = wxT("Add a new M"); break;
+		case L:
+			undodesc = wxT("Add a new L"); break;
+		case B:
+			undodesc = wxT("Add a new B"); break;
+		}
+		newcommand = NULL;
+		// we need to manually refresh the GUI to draw the new control points
+		RefreshDisplay();
+	}
+	else if ( draw_mode == MODE_DEL // if it's delete mode
+				&& mousedownAt_point != NULL // and mouse down at a point
+				&& mousedownAt_point == pointedAt_point ) // and released at the same point
+	{
+		// first take care of mouse readings
+		pointedAt_point = NULL;
+		Point *lastmousedownAt_point = mousedownAt_point;
+		mousedownAt_point = NULL;
+
+		// try deleting
+		CMDTYPE t = lastmousedownAt_point->cmd_main->type;
+		if ( DeleteCommand( lastmousedownAt_point->cmd_main ) )
+		{
+			ClearPointsSelection();
+			SetHighlighted( NULL, NULL );
+			RefreshDisplay();
+			switch (t)
+			{
+			case M:
+				undodesc = wxT("Delete a M"); break;
+			case L:
+				undodesc = wxT("Delete a L"); break;
+			case B:
+				undodesc = wxT("Delete a B"); break;
+			}
+		}
+		else
+		{
+			RefreshDisplay(); // redraw before showing the error box
+			wxMessageDialog msgb(m_frame, 
+			_T("You must delete that command/point last"), 
+			_T("Error"), wxOK | wxICON_EXCLAMATION );
+			msgb.ShowModal();
+		}
+	}
+	else if ( lastDrag_left && dragAnchor_left ) // point selection
+	{
+		if (lastDrag_left && dragAnchor_left != lastDrag_left)
+		    delete lastDrag_left;
+	    delete dragAnchor_left;			
+		lastDrag_left = NULL;
+		dragAnchor_left = NULL;
+	}
+	
+	if (dragOrigin)
+	{
+		dragOrigin = false;
+		RefreshDisplay(); // clear the crosshair
+	}
+
+	rectbound2upd = -1;
+	rectbound2upd2 = -1;
+    backupowner = NONE;
+
+	if (!undodesc.IsSameAs(""))
+	{
+		AddUndo( undodesc );
+		undodesc = "";
+		RefreshUndocmds();
+	}
+
+	mousedownAt_point = NULL;
+
+	if (HasCapture())
+		ReleaseMouse();
+	capturemouse_left = false;
+	
+	RefreshDisplay();
+}
+
+// Set up to drag points, if any
+void ASSDrawCanvas::OnMouseLeftDown(wxMouseEvent& event)
+{
+
+    // no drawing in preview mode
+	if (preview_mode /*|| was_preview_mode*/)
+		return;
+
+	wxPoint q = event.GetPosition();
+
+	// wxPoint to Point
+	int px, py;
+	pointsys->FromWxPoint(q, px, py);
+	
+	// create new cmd if in draw mode / or delete point if del tool selected
+	switch (draw_mode)
+	{
+	case MODE_M:
+		newcommand = NewCmd(M, px, py);
+		break;
+	case MODE_L:
+		newcommand = NewCmd(L, px, py);
+		break;
+	case MODE_B:
+		newcommand = NewCmd(B, px, py);
+		break;
+	}
+
+	// continue working on the new command (if any)
+	// only if it is not mouse down on any control point
+	if (newcommand != NULL)
+	{
+		if (pointedAt_point != NULL && pointedAt_point->type == CP)
+		{
+			// oops, user clicked on a control point so cancel new command
+			// and let him drag the control point
+			delete newcommand;
+            newcommand = NULL;
+		}
+		else 
+		{
+			// first set to drag the new command no matter what
+			mousedownAt_point = newcommand->m_point;
+	      
+			// if user drags from existing point, insert the new command
+			// else append the new command
+			if (pointedAt_point != NULL)
+				InsertCmd( newcommand, pointedAt_point->cmd_main );
+			else
+			{
+				if (cmds.empty() && newcommand->type != M)
+					AppendCmd( M, px, py );
+				newcommand = AppendCmd( newcommand );
+			}
+
+			pointedAt_point = mousedownAt_point;
+	           
+			//highlight it
+			SetHighlighted( newcommand, newcommand->m_point );
+		}                    
+	}
+
+	// we already calculated pointedAt_point in OnMouseMove() so just use it
+	mousedownAt_point = pointedAt_point;
+	SELECTMODE smode = GetSelectMode(event);
+	if (mousedownAt_point && !mousedownAt_point->isselected)
+	{
+		if (smode == NEW)
+		{
+			ClearPointsSelection();
+			mousedownAt_point->isselected = true;
+			selected_points.insert(mousedownAt_point);
+		}
+		else
+		{
+			wxPoint wxp = mousedownAt_point->ToWxPoint();
+			SelectPointsWithin(wxp.x, wxp.x, wxp.y, wxp.y, smode);
+		}
+	}
+	else if (!mousedownAt_point && smode == NEW)
+		ClearPointsSelection();
+
+	if ( mousedownAt_point == NULL && px == 0 && py == 0 )
+		dragOrigin = true;
+
+	if ( mousedownAt_point == NULL && !dragOrigin )
+	{
+		dragAnchor_left = new wxPoint(q.x, q.y);
+		lastDrag_left = dragAnchor_left;
+	}
+
+	if (InitiateDraggingIfTransformMode())
+	    backupowner = LEFT;
+	
+	CaptureMouse();
+	capturemouse_left = true;
+	RefreshDisplay();
+
+	event.Skip( true );
+}
+
+// End drag the canvas
+void ASSDrawCanvas::OnMouseRightUp(wxMouseEvent& event)
+{
+	ProcessOnMouseRightUp();
+	event.Skip( true );
+}
+
+void ASSDrawCanvas::ProcessOnMouseRightUp()
+{
+	if (!capturemouse_right) return;
+
+    if (lastDrag_right && dragAnchor_right != lastDrag_right)
+        delete lastDrag_right;
+    if (dragAnchor_right)
+        delete dragAnchor_right;
+	dragAnchor_right = NULL;
+	lastDrag_right = NULL;
+
+	// don't crash the program
+	if (HasCapture())
+		ReleaseMouse();
+	capturemouse_right = false;
+
+	rectbound2upd = -1;
+	rectbound2upd2 = -1;
+    backupowner = NONE;
+
+	if (!undodesc.IsSameAs(""))
+	{
+		AddUndo( undodesc );
+		undodesc = "";
+		RefreshUndocmds();
+	}
+
+	RefreshDisplay();
+	SetFocus();
+}
+
+// Set up to drag the canvas
+void ASSDrawCanvas::OnMouseRightDown(wxMouseEvent &event)
+{
+	wxPoint q = event.GetPosition();
+	dragAnchor_right = new wxPoint(q.x, q.y);
+	lastDrag_right = dragAnchor_right;
+	CaptureMouse();
+	capturemouse_right = true;
+
+	if (InitiateDraggingIfTransformMode())
+	    backupowner = RIGHT;
+//	was_preview_mode = preview_mode;
+//	preview_mode = false;
+
+	event.Skip( true );
+}
+
+// Reset to point-and-drag mode
+void ASSDrawCanvas::OnMouseRightDClick(wxMouseEvent& event)
+{
+	wxMenu* menu = new wxMenu();
+
+	if (pointedAt_point)
+	{
+		ProcessOnMouseLeftUp();
+		ProcessOnMouseRightUp();
+		dblclicked_point_right = pointedAt_point;
+		pointedAt_point = NULL;
+		wxMenuItem *cmdmenuitem = new wxMenuItem(menu, MENU_DUMMY, dblclicked_point_right->cmd_main->ToString());
+		wxFont f = cmdmenuitem->GetFont();
+		f.SetWeight(wxFONTWEIGHT_BOLD);
+		cmdmenuitem->SetFont(f);
+		menu->Append(cmdmenuitem); 
+		menu->Enable(MENU_DUMMY, false);
+		switch (dblclicked_point_right->cmd_main->type)
+		{
+			case L:
+				menu->Append(MENU_DRC_LNTOBEZ, "Convert to Bezier curve (B command)");
+				break;
+			case B:
+				if (dblclicked_point_right->type != MP) break;
+				menu->AppendCheckItem(MENU_DRC_BEZTOLN, "Convert to line (L command)");
+				if (dblclicked_point_right->cmd_next && dblclicked_point_right->cmd_next->type == B)
+				{
+					menu->AppendCheckItem(MENU_DRC_C1CONTBEZ, "Smooth connection");
+					if (static_cast<DrawCmd_B*>(dblclicked_point_right->cmd_main)->C1Cont)
+						menu->Check(MENU_DRC_C1CONTBEZ, true);
+				}
+				break;
+		}
+
+	}
+	else
+	{
+		menu->Append(MENU_DRC_MOVE00, "Move [0,0] here");
+		menu->AppendSeparator();
+		menu->AppendRadioItem(MODE_ARR, _T("Mode: D&rag"));
+		menu->AppendRadioItem(MODE_M, _T("Mode: Draw &M"));
+		menu->AppendRadioItem(MODE_L, _T("Mode: Draw &L"));
+		menu->AppendRadioItem(MODE_B, _T("Mode: Draw &B"));
+		menu->AppendRadioItem(MODE_DEL, _T("Mode: &Delete"));
+		menu->Check(GetDrawMode(), true);
+	}
+
+	if (menu->GetMenuItemCount() > 0) // only if there is menu item
+	{
+		SetHighlighted(NULL, NULL);
+		mousedownAt_point = NULL;
+		RefreshDisplay();
+		PopupMenu(menu);
+	}
+	delete menu;
+
+	event.Skip( true );
+}
+
+bool ASSDrawCanvas::InitiateDraggingIfTransformMode()
+{
+	if (IsTransformMode() && isshapetransformable && backupowner == NONE)
+	{
+		for (int i = 0; i < 4; i++)
+			backup[i] = rectbound2[i];
+		UpdateTranformModeRectCenter();
+		return true;
+	}
+	else
+		return false;
+}
+
+void ASSDrawCanvas::UpdateTranformModeRectCenter()
+{
+	double cx, cy;
+	if (agg::calc_intersection(rectbound2[0].x, rectbound2[0].y, rectbound2[2].x, rectbound2[2].y,
+		rectbound2[1].x, rectbound2[1].y, rectbound2[3].x, rectbound2[3].y, &cx, &cy))
+	{ 
+		rectcenter = wxRealPoint(cx, cy); 
+	}	
+}
+
+bool ASSDrawCanvas::GetThe4thPoint(double ox, double oy, double a1x, double a1y, double a2x, double a2y, double *x, double *y)
+{
+	/*
+	return agg::calc_intersection(a1x, a1y,
+		a2x + a1x - ox,
+		a2y + a1y - oy,
+		a2x, a2y,
+		a1x + a2x - ox,
+		a1y + a2y - oy,
+		x, y);	//*/
+	
+	*x = a1x + a2x - ox;
+	*y = a1y + a2y - oy;
+	return true;
+}
+
+// Mousewheel
+void ASSDrawCanvas::OnMouseWheel(wxMouseEvent &event)
+{
+	double amount = event.GetWheelRotation() / event.GetWheelDelta();
+	if (event.ControlDown()) amount /= 10.0;
+	bgimg.new_center = wxRealPoint(mouse_point.x, mouse_point.y);
+	ChangeZoomLevel( amount, mouse_point );
+}
+
+void ASSDrawCanvas::ChangeZoomLevelTo( double zoom, wxPoint bgzoomctr )
+{
+	ChangeZoomLevel(zoom - pointsys->scale, bgzoomctr);
+}
+
+void ASSDrawCanvas::ChangeZoomLevel( double amount, wxPoint bgzoomctr )
+{
+	double old_scale = pointsys->scale;
+	/*
+	switch (drag_mode)
+	{
+	case DRAG_BGIMG:
+	    ChangeBackgroundZoomLevel(bgimg.scale + amount / 10.0,  wxRealPoint(bgzoomctr.x, bgzoomctr.y));
+		break;
+
+	case DRAG_BOTH:
+		ChangeDrawingZoomLevel( amount );
+	    ChangeBackgroundZoomLevel(bgimg.scale * pointsys->scale / old_scale, 
+			wxRealPoint(pointsys->originx, pointsys->originy));
+		break;
+
+	case DRAG_DWG:
+		ChangeDrawingZoomLevel( amount );
+		break;
+	}
+	*/
+	
+	if (CanZoom() && drag_mode.drawing)
+		ChangeDrawingZoomLevel( amount );
+
+	if (CanZoom() && drag_mode.bgimg)
+		if (drag_mode.drawing)
+		    ChangeBackgroundZoomLevel(bgimg.scale * pointsys->scale / old_scale, wxRealPoint(pointsys->originx, pointsys->originy));
+		else
+		    ChangeBackgroundZoomLevel(bgimg.scale + amount / 10.0,  wxRealPoint(bgzoomctr.x, bgzoomctr.y));
+	
+	RefreshDisplay();
+}
+
+void ASSDrawCanvas::ChangeDrawingZoomLevel( double scrollamount )
+{
+	if (!CanZoom()) return;
+    double zoom = pointsys->scale + scrollamount;
+    if (zoom <= 50.0)
+	{
+		if (zoom < 1.0) zoom = 1.0;
+		pointsys->scale = zoom;
+	}
+	
+	m_frame->UpdateFrameUI();
+}
+
+void ASSDrawCanvas::ChangeBackgroundZoomLevel(double zoom, wxRealPoint newcenter)
+{
+	bgimg.new_scale = zoom;
+	bgimg.new_center = newcenter;
+	if (bgimg.new_scale < 0.01) bgimg.new_scale = 0.01;
+	UpdateBackgroundImgScalePosition();	
+}
+
+void ASSDrawCanvas::MoveCanvasOriginTo(double originx, double originy)
+{
+	MoveCanvas(originx - pointsys->originx, originy - pointsys->originy);
+}
+
+void ASSDrawCanvas::MoveCanvas(double xamount, double yamount)
+{
+	/*
+	if (drag_mode == DRAG_DWG || drag_mode == DRAG_BOTH)
+		MoveCanvasDrawing(xamount, yamount);
+	if (drag_mode == DRAG_BGIMG || drag_mode == DRAG_BOTH)
+		MoveCanvasBackground(xamount, yamount);
+	*/
+	if (CanMove() && drag_mode.drawing)
+		MoveCanvasDrawing(xamount, yamount);
+	if (CanMove() && drag_mode.bgimg)
+		MoveCanvasBackground(xamount, yamount);
+}
+
+void ASSDrawCanvas::MoveCanvasDrawing(double xamount, double yamount)
+{
+	if (!CanMove()) return;
+	pointsys->originx += xamount;
+	pointsys->originy += yamount;		
+	if (IsTransformMode())
+	{
+	    for (int i = 0; i < 4; i++)
+	    {
+	    	rectbound[i].x += (int) xamount;
+	    	rectbound[i].y += (int) yamount;
+	    	rectbound2[i].x += (int) xamount;
+	    	rectbound2[i].y += (int) yamount;
+		}
+		unsigned vertices = backupcmds.total_vertices();
+		double x, y;
+		for (int i = 0; i < vertices; i++)
+		{
+			backupcmds.vertex(i, &x, &y);
+	        backupcmds.modify_vertex(i, x + xamount, y + yamount);
+		}
+	}
+}
+
+void ASSDrawCanvas::MoveCanvasBackground(double xamount, double yamount)
+{
+	//bgimg.new_center.x += xamount, bgimg.new_center.y += yamount;
+	bgimg.new_disp.x += xamount;
+	bgimg.new_disp.y += yamount;
+	UpdateBackgroundImgScalePosition();	
+}
+
+void ASSDrawCanvas::OnSelect_ConvertLineToBezier(wxCommandEvent& WXUNUSED(event))
+{
+	if (!dblclicked_point_right) return;
+	AddUndo( wxT("Convert Line to Bezier") );
+	DrawCmd_B *newB = new DrawCmd_B(dblclicked_point_right->x(), dblclicked_point_right->y(), 
+		pointsys, dblclicked_point_right->cmd_main);
+	InsertCmd ( newB, dblclicked_point_right->cmd_main );
+	ClearPointsSelection();
+	SetHighlighted(NULL, NULL);
+	DeleteCommand(dblclicked_point_right->cmd_main);
+	pointedAt_point = newB->m_point;
+	newB->Init();
+	RefreshDisplay();
+	RefreshUndocmds();
+}
+
+void ASSDrawCanvas::OnSelect_ConvertBezierToLine(wxCommandEvent& WXUNUSED(event))
+{
+	if (!dblclicked_point_right) return;
+	AddUndo( wxT("Convert Bezier to Line") );
+	DrawCmd_L *newL = new DrawCmd_L(dblclicked_point_right->x(), dblclicked_point_right->y(), pointsys, dblclicked_point_right->cmd_main);
+	InsertCmd ( newL, dblclicked_point_right->cmd_main );
+	ClearPointsSelection();
+	SetHighlighted(NULL, NULL);
+	DeleteCommand(dblclicked_point_right->cmd_main);
+	pointedAt_point = newL->m_point;
+	newL->Init();
+	RefreshDisplay();
+	RefreshUndocmds();
+}
+
+void ASSDrawCanvas::OnSelect_C1ContinuityBezier(wxCommandEvent& WXUNUSED(event))
+{
+	if (!dblclicked_point_right) return;
+	DrawCmd_B *cmdb = static_cast<DrawCmd_B*>(dblclicked_point_right->cmd_main);
+	AddUndo( wxT(cmdb->C1Cont? "Unset continuous":"Set continuous") );
+	cmdb->C1Cont = !cmdb->C1Cont;
+	RefreshUndocmds();
+}
+
+void ASSDrawCanvas::OnSelect_Move00Here(wxCommandEvent& WXUNUSED(event))
+{
+	AddUndo( wxT("Move origin") );
+	int wx, wy;
+	pointsys->FromWxPoint(mouse_point, wx, wy);
+	wxPoint wxp = pointsys->ToWxPoint(wx, wy);
+	pointsys->originx = wxp.x;
+	pointsys->originy = wxp.y;
+	MovePoints(-wx, -wy);
+	RefreshDisplay();
+	RefreshUndocmds();
+}
+
+void ASSDrawCanvas::ConnectSubsequentCmds (DrawCmd* cmd1, DrawCmd* cmd2)
+{
+	ASSDrawEngine::ConnectSubsequentCmds(cmd1, cmd2);
+	if (cmd1 && cmd1->type == B)
+	{
+		DrawCmd_B *cmd1b = static_cast< DrawCmd_B* >(cmd1);
+		cmd1b->C1Cont = false;
+	}
+}
+
+void ASSDrawCanvas::EnforceC1Continuity (DrawCmd* cmd, Point* pnt)
+{
+	if (!cmd || !pnt) return;
+	if (cmd->type != B && cmd->type != S) return;
+	if (pnt->type == MP) return;
+	Point *theotherpoint, *mainpoint;
+	if (pnt->num == 1)
+	{
+		if (!cmd->prev || (cmd->prev->type != B && cmd->prev->type != S)) return;
+		DrawCmd_B *prevb = static_cast< DrawCmd_B* >(cmd->prev);
+		if (!prevb->C1Cont) return;
+		PointList::iterator it = prevb->controlpoints.end();
+		it--;
+		theotherpoint = *it;
+		mainpoint = prevb->m_point;
+	}
+	else if (pnt->num = cmd->controlpoints.size())
+	{
+		DrawCmd_B *thisb = static_cast< DrawCmd_B* >(cmd);
+		if (!thisb->C1Cont) return;
+		theotherpoint = *(cmd->m_point->cmd_next->controlpoints.begin());		
+		mainpoint = thisb->m_point;
+	}
+	else
+		return;
+	theotherpoint->setXY( mainpoint->x() + mainpoint->x() - pnt->x(),
+		mainpoint->y() + mainpoint->y() - pnt->y() );
+}
+
+// Undo/Redo system
+void ASSDrawCanvas::AddUndo( wxString desc ) 
+{
+	PrepareUndoRedo(_undo, false, "", desc);
+	undos.push_back( _undo );
+	// also empty redos
+	redos.clear();
+	m_frame->UpdateUndoRedoMenu();
+}
+
+bool ASSDrawCanvas::UndoOrRedo(bool isundo)
+{
+	std::list<UndoRedo>* main = (isundo? &undos:&redos);
+	std::list<UndoRedo>* sub = (isundo? &redos:&undos);
+
+	if (main->empty())
+		return false;
+
+	UndoRedo r = main->back();
+	// push into sub
+	UndoRedo nr(r);
+	PrepareUndoRedo(nr, true, GenerateASS(), r.desc); 
+	//PrepareUndoRedo(nr, false, "", r.desc);
+	sub->push_back( nr );
+	// parse
+	r.Export(this);
+	// delete that
+	std::list<UndoRedo>::iterator iter = main->end();
+	iter--;
+	main->erase(iter);
+
+	// reset some values before refreshing
+	mousedownAt_point = NULL;
+	pointedAt_point = NULL;
+	SetHighlighted ( NULL, NULL );
+	ClearPointsSelection();
+	RefreshDisplay();
+	RefreshUndocmds();
+	return true;
+}
+
+bool ASSDrawCanvas::Undo()
+{
+	return UndoOrRedo( true );
+}
+
+bool ASSDrawCanvas::Redo()
+{
+	return UndoOrRedo( false );
+}
+
+wxString ASSDrawCanvas::GetTopUndo()
+{
+	if (undos.empty())
+		return "";
+	else
+		return undos.back().desc;
+}
+
+wxString ASSDrawCanvas::GetTopRedo()
+{
+	if (redos.empty())
+		return "";
+	else
+		return redos.back().desc;
+}
+
+void ASSDrawCanvas::RefreshUndocmds()
+{
+	_undo.Import(this, true, GenerateASS());
+}
+
+void ASSDrawCanvas::PrepareUndoRedo(UndoRedo& ur, bool prestage, wxString cmds, wxString desc) 
+{
+	ur.Import(this, prestage, cmds);
+	ur.desc = desc;	
+}
+
+// set command and point to highlight
+void ASSDrawCanvas::SetHighlighted ( DrawCmd* cmd, Point* point )
+{
+     hilite_cmd = cmd;
+     hilite_point = point;
+}
+
+int ASSDrawCanvas::SelectPointsWithin( int lx, int rx, int ty, int by, SELECTMODE smode )
+{
+
+	DrawCmdList::iterator iterate = cmds.begin();
+	for (; iterate != cmds.end(); iterate++)
+	{
+		wxPoint wx = (*iterate)->m_point->ToWxPoint();
+
+		if (wx.x >= lx && wx.x <= rx && wx.y >= ty && wx.y <= by)
+			(*iterate)->m_point->isselected = (smode != DEL);
+		else
+	    	(*iterate)->m_point->isselected &= (smode != NEW);
+
+		if ((*iterate)->m_point->isselected)
+	    	selected_points.insert((*iterate)->m_point);
+	    else
+			selected_points.erase((*iterate)->m_point);
+
+		PointList::iterator pnt_iterator = (*iterate)->controlpoints.begin();
+		PointList::iterator end = (*iterate)->controlpoints.end();
+		for (; pnt_iterator != end; pnt_iterator++)
+		{
+			wxPoint wx = (*pnt_iterator)->ToWxPoint();
+
+			if (wx.x >= lx && wx.x <= rx && wx.y >= ty && wx.y <= by)
+	    		(*pnt_iterator)->isselected = (smode != DEL);
+		    else
+	    		(*pnt_iterator)->isselected &= (smode != NEW);
+			
+			if ((*pnt_iterator)->isselected)
+				selected_points.insert(*pnt_iterator);
+			else
+				selected_points.erase(*pnt_iterator);
+		}
+	}
+
+	return selected_points.size();
+
+}
+
+void ASSDrawCanvas::ClearPointsSelection()
+{
+	if (!selected_points.empty())
+	{
+		PointSet::iterator piter = selected_points.begin();
+		for (; piter != selected_points.end(); piter++)
+		{
+			(*piter)->isselected = false;
+		}
+		selected_points.clear();
+	}
+}
+
+SELECTMODE ASSDrawCanvas::GetSelectMode(wxMouseEvent& event)
+{
+	SELECTMODE smode = NEW;
+	bool CtrlDown = event.CmdDown();
+	bool AltDown = event.AltDown();
+	if (CtrlDown && !AltDown) smode = ADD;
+	else if (!CtrlDown && AltDown) smode = DEL;
+	return smode;
+}
+
+void ASSDrawCanvas::DoDraw( RendererBase& rbase, RendererPrimitives& rprim, RendererSolid& rsolid, agg::trans_affine& mtx )
+{
+	ASSDrawEngine::Draw_Clear( rbase );
+	int ww, hh; GetClientSize(&ww, &hh);
+
+	if (bgimg.bgbmp)
+	{ 
+		rasterizer.reset();
+	    interpolator_type interpolator(bgimg.img_mtx);
+	    PixelFormat::AGGType ipixfmt(bgimg.ibuf);
+		span_gen_type spangen(ipixfmt, agg::rgba_pre(0, 0, 0), interpolator);
+		agg::conv_transform< agg::path_storage > bg_border(bgimg.bg_path, bgimg.path_mtx);
+		agg::conv_clip_polygon< agg::conv_transform< agg::path_storage > > bg_clip(bg_border);
+		bg_clip.clip_box(0, 0, ww, hh);
+		rasterizer.add_path(bg_clip);
+		agg::render_scanlines_aa(rasterizer, scanline, rbase, bgimg.spanalloc, spangen);
+	}
+
+	ASSDrawEngine::Draw_Draw( rbase, rprim, rsolid, mtx, preview_mode? rgba_shape:rgba_shape_normal );
+		
+	if (!preview_mode)
+	{
+		// [0, 0]
+		rasterizer.reset();
+		agg::path_storage org_path;
+		org_path.move_to(0, m_frame->sizes.origincross);
+		org_path.line_to(0, -m_frame->sizes.origincross);
+		org_path.move_to(m_frame->sizes.origincross, 0);
+		org_path.line_to(-m_frame->sizes.origincross, 0);
+		agg::conv_transform< agg::path_storage > org_path_t(org_path, mtx);
+	    agg::conv_curve< agg::conv_transform< agg::path_storage > > crosshair(org_path_t);
+		agg::conv_stroke< agg::conv_curve< agg::conv_transform< agg::path_storage > > > chstroke(crosshair);
+		rasterizer.add_path(chstroke);
+		rsolid.color(rgba_origin);
+		render_scanlines(rsolid, false);
+
+		if (IsTransformMode() && isshapetransformable)
+		{
+			if (draw_mode == MODE_SCALEROTATE)
+			{
+				// rotation centerpoint
+				rasterizer.reset();
+				double len = 10.0; //m_frame->sizes.origincross * pointsys->scale;
+				org_path.free_all();
+				org_path.move_to(rectcenter.x - len, rectcenter.y - len);
+				org_path.line_to(rectcenter.x + len, rectcenter.y + len);
+				org_path.move_to(rectcenter.x + len, rectcenter.y - len);
+				org_path.line_to(rectcenter.x - len, rectcenter.y + len);
+				agg::conv_stroke< agg::path_storage > cstroke(org_path);
+				rasterizer.add_path(cstroke);
+				agg::ellipse circ(rectcenter.x, rectcenter.y, len, len);
+				agg::conv_stroke< agg::ellipse > c(circ);
+				rasterizer.add_path(c);
+				rsolid.color(rgba_origin);
+				render_scanlines(rsolid, false);
+			}
+
+			rasterizer.reset();
+			agg::path_storage org_path;
+			org_path.move_to(rectbound2[0].x, rectbound2[0].y);
+			org_path.line_to(rectbound2[1].x, rectbound2[1].y);
+			org_path.line_to(rectbound2[2].x, rectbound2[2].y);
+			org_path.line_to(rectbound2[3].x, rectbound2[3].y);
+			org_path.line_to(rectbound2[0].x, rectbound2[0].y);
+			agg::conv_stroke<agg::path_storage> chstroke(org_path);
+			chstroke.width(1);
+			rsolid.color(rgba_origin);
+			rasterizer.add_path(chstroke);
+			if (rectbound2upd != -1)
+			{
+				agg::ellipse circ(rectbound2[rectbound2upd].x, rectbound2[rectbound2upd].y, 
+					pointsys->scale, pointsys->scale);
+				agg::conv_contour< agg::ellipse > c(circ);
+				rasterizer.add_path(c);
+			}
+			if (rectbound2upd2 != -1)
+			{
+				agg::ellipse circ(rectbound2[rectbound2upd2].x, rectbound2[rectbound2upd2].y, 
+					pointsys->scale, pointsys->scale);
+				agg::conv_contour< agg::ellipse > c(circ);
+				rasterizer.add_path(c);
+			}
+			render_scanlines(rsolid, false);
+		}
+		else
+		{
+			// outlines
+			agg::conv_stroke< agg::conv_transform< agg::path_storage > > bguidestroke(*rb_path);
+			bguidestroke.width(1);
+			rsolid.color(rgba_guideline);
+			rasterizer.add_path(bguidestroke);
+			render_scanlines(rsolid);
+	
+			agg::conv_stroke< agg::conv_curve< agg::conv_transform< agg::path_storage > > > stroke(*rm_curve);
+			stroke.width(1);
+			rsolid.color(rgba_outline);
+			rasterizer.add_path(stroke);
+			render_scanlines(rsolid);
+	
+			double diameter = pointsys->scale;
+			double radius = diameter / 2.0;
+			// hilite
+			if (hilite_cmd && hilite_cmd->type != M)
+			{
+				rasterizer.reset();
+				agg::path_storage h_path;
+				AddDrawCmdToAGGPathStorage(hilite_cmd, h_path, HILITE);
+				agg::conv_transform< agg::path_storage> h_path_trans(h_path, mtx);
+			    agg::conv_curve< agg::conv_transform< agg::path_storage> > curve(h_path_trans);
+				agg::conv_dash< agg::conv_curve< agg::conv_transform< agg::path_storage > > > d(curve);
+				d.add_dash(10,5);
+				agg::conv_stroke< agg::conv_dash< agg::conv_curve< agg::conv_transform< agg::path_storage > > > > stroke(d);
+				stroke.width(3);
+				rsolid.color(rgba_outline);
+				rasterizer.add_path(stroke);
+				render_scanlines(rsolid);
+			}
+			
+			// m_point
+			rasterizer.reset();
+			DrawCmdList::iterator ci = cmds.begin();
+			while (ci != cmds.end())
+			{
+				double lx = (*ci)->m_point->x() * pointsys->scale + pointsys->originx - radius;
+				double ty = (*ci)->m_point->y() * pointsys->scale + pointsys->originy - radius;
+				agg::path_storage sqp = agghelper::RectanglePath(lx, lx + diameter, ty, ty + diameter);
+				agg::conv_contour< agg::path_storage > c(sqp);
+				rasterizer.add_path(c);
+				ci++;
+			}
+			render_scanlines_aa_solid(rbase, rgba_mainpoint);
+	
+			// control_points
+			rasterizer.reset();
+			ci = cmds.begin();
+			while (ci != cmds.end())
+			{
+				PointList::iterator pi = (*ci)->controlpoints.begin();
+				while (pi != (*ci)->controlpoints.end())
+				{
+					agg::ellipse circ((*pi)->x() * pointsys->scale + pointsys->originx, 
+						(*pi)->y() * pointsys->scale + pointsys->originy, radius, radius);
+					agg::conv_contour< agg::ellipse > c(circ);
+					rasterizer.add_path(c);
+					pi++;
+				}
+				ci++;
+			}
+			render_scanlines_aa_solid(rbase, rgba_controlpoint);
+		
+			// selection
+			rasterizer.reset();
+			PointSet::iterator si = selected_points.begin();
+			while (si != selected_points.end())
+			{
+				agg::ellipse circ((*si)->x() * pointsys->scale + pointsys->originx, 
+					(*si)->y() * pointsys->scale + pointsys->originy, radius + 3, radius + 3);
+				agg::conv_stroke< agg::ellipse > s(circ);
+				rasterizer.add_path(s);
+				si++;
+			}
+			render_scanlines_aa_solid(rbase, rgba_selectpoint);
+	
+			// hover
+			if (hilite_point)
+			{
+				rasterizer.reset();
+				agg::ellipse circ(hilite_point->x() * pointsys->scale + pointsys->originx, 
+					hilite_point->y() * pointsys->scale + pointsys->originy, radius + 3, radius + 3);
+				agg::conv_stroke< agg::ellipse > s(circ);
+				s.width(2);
+				rasterizer.add_path(s);
+				render_scanlines_aa_solid(rbase, rgba_selectpoint);
+	
+				rasterizer.reset();
+				agg::gsv_text t;
+				t.flip(true);
+				t.size(8.0);
+				wxPoint pxy = hilite_point->ToWxPoint(true);
+				t.start_point(pxy.x + 5, pxy.y -5 );
+				t.text(wxString::Format("%d,%d", hilite_point->x(), hilite_point->y()));
+				agg::conv_stroke< agg::gsv_text > pt(t);
+				pt.line_cap(agg::round_cap);
+				pt.line_join(agg::round_join);
+				pt.width(1.5);
+				rasterizer.add_path(pt);
+				rsolid.color(agg::rgba(0,0,0));
+				render_scanlines(rsolid, false);
+				
+				rasterizer.reset();
+				agg::path_storage sb_path;
+				sb_path.move_to(pxy.x, 0);
+				sb_path.line_to(pxy.x, hh);
+				sb_path.move_to(0, pxy.y);
+				sb_path.line_to(ww, pxy.y);
+			    agg::conv_curve< agg::path_storage > curve(sb_path);
+				agg::conv_dash< agg::conv_curve< agg::path_storage > > d(curve);
+				d.add_dash(10,5);
+				agg::conv_stroke< agg::conv_dash< agg::conv_curve< agg::path_storage > > > stroke(d);
+				stroke.width(1);
+				rsolid.color(agg::rgba(0,0,0,0.5));
+				rasterizer.add_path(stroke);
+				render_scanlines(rsolid);
+			}
+			
+			// selection box
+			if (lastDrag_left)
+			{
+				double x1 = lastDrag_left->x, y1 = lastDrag_left->y;
+				double x2 = dragAnchor_left->x, y2 = dragAnchor_left->y;
+				double lx, rx, ty, by;
+				if (x1 < x2) lx = x1, rx = x2;
+				else lx = x2, rx = x1;
+				if (y1 < y2) ty = y1, by = y2;
+				else ty = y2, by = y1;
+				rasterizer.reset();
+				agg::path_storage sb_path = agghelper::RectanglePath(lx, rx, ty, by);
+			    agg::conv_curve< agg::path_storage > curve(sb_path);
+				agg::conv_dash< agg::conv_curve< agg::path_storage > > d(curve);
+				d.add_dash(10,5);
+				agg::conv_stroke< agg::conv_dash< agg::conv_curve< agg::path_storage > > > stroke(d);
+				stroke.width(1.0);
+				rsolid.color(agg::rgba(0,0,0,0.5));
+				rasterizer.add_path(stroke);
+				render_scanlines(rsolid);
+			}
+		}		
+	}
+	
+	// ruler
+	int w, h;
+	GetClientSize( &w, &h );
+	double scale = pointsys->scale;
+	double coeff = 9 / scale + 1;
+	int numdist = (int) floor(coeff) * 5;
+	{
+		rsolid.color(rgba_ruler_h);
+		rasterizer.reset();
+		agg::path_storage rlr_path;
+		double start = pointsys->originx;
+		int t = - (int) floor(start / scale);
+		double s = (start + t * scale);
+		double collect = s;
+		int len;
+
+		for (; s <= w; s += scale)
+		{
+			bool longtick = t % numdist == 0;
+			if (longtick)
+			{
+				len = 10;
+				agg::gsv_text txt;
+				txt.flip(true);
+				txt.size(6.0);
+				txt.start_point(s, 20);
+				txt.text(wxString::Format("%d", t));
+				agg::conv_stroke< agg::gsv_text > pt(txt);
+				rasterizer.add_path(pt);
+			}
+			else
+				len = 5;
+			t++ ;
+			collect += scale;
+			if (collect > 5.0)
+			{
+				collect = 0.0;
+				rlr_path.move_to(s, 0);
+				rlr_path.line_to(s, len);
+			}
+		}
+		agg::conv_stroke< agg::path_storage > rlr_stroke(rlr_path);
+		rlr_stroke.width(1);
+		rasterizer.add_path(rlr_stroke);
+		render_scanlines(rsolid, false);
+	}
+	{
+		rasterizer.reset();
+		rsolid.color(rgba_ruler_v);
+		agg::path_storage rlr_path;
+		double start = pointsys->originy;
+		int t = - (int) floor(start / scale);
+		double s = (start + t * scale);
+		double collect = 0;
+		int len;
+
+		for (; s <= h; s += scale)
+		{
+			bool longtick = t % numdist == 0;
+			if (longtick)
+			{
+				len = 10;
+				agg::gsv_text txt;
+				txt.flip(true);
+				txt.size(6.0);
+				txt.start_point(12, s);
+				txt.text(wxString::Format("%d", t));
+				agg::conv_stroke< agg::gsv_text > pt(txt);
+				rasterizer.add_path(pt);
+			}
+			else
+				len = 5;
+			t++ ;
+			collect += scale;
+			if (collect > 5.0)
+			{
+				collect = 0.0;
+				rlr_path.move_to(0, s);
+				rlr_path.line_to(len, s);
+			}
+		}
+		agg::conv_stroke< agg::path_storage > rlr_stroke(rlr_path);
+		rlr_stroke.width(1);
+		rasterizer.add_path(rlr_stroke);
+		render_scanlines(rsolid, false);
+	}
+
+}
+
+void ASSDrawCanvas::ReceiveBackgroundImageFileDropEvent(const wxString& filename)
+{
+	const wxChar *shortfname = wxFileName::FileName(filename).GetFullName().c_str();
+	m_frame->SetStatusText(wxString::Format("Loading '%s' as canvas background ...", shortfname), 1);
+	wxImage img;
+	img.LoadFile(filename);
+	if (img.IsOk())
+	{
+		SetBackgroundImage(img, filename);
+	}
+	m_frame->SetStatusText(wxT("Canvas background loaded"), 1);
+}
+
+void ASSDrawCanvas::RemoveBackgroundImage()
+{
+	if (bgimg.bgimg) delete bgimg.bgimg;
+	bgimg.bgimg = NULL;
+	if (bgimg.bgbmp) delete bgimg.bgbmp;
+	bgimg.bgbmp = NULL;
+	bgimg.bgimgfile = "";
+	RefreshDisplay();
+	drag_mode = DRAGMODE();
+	bgimg.alpha_dlg->Show(false);
+	m_frame->UpdateFrameUI();
+}
+
+void ASSDrawCanvas::SetBackgroundImage(const wxImage& img, wxString fname, bool ask4alpha)
+{
+	if (bgimg.bgimg) delete bgimg.bgimg;
+	bgimg.bgimg = new wxImage(img);
+	bgimg.bgimgfile = fname;
+	PrepareBackgroundBitmap(bgimg.alpha);
+    UpdateBackgroundImgScalePosition(true);
+	RefreshDisplay();
+	m_frame->UpdateFrameUI();
+	if (ask4alpha && m_frame->behaviors.autoaskimgopac)
+		AskUserForBackgroundAlpha();
+}
+
+void ASSDrawCanvas::AskUserForBackgroundAlpha()
+{
+	bgimg.alpha_slider->SetValue((int) (100 - bgimg.alpha * 100));
+	bgimg.alpha_dlg->Show();
+	SetFocus();
+}
+	
+void ASSDrawCanvas::PrepareBackgroundBitmap(double alpha)
+{
+	if (alpha >= 0.0 && alpha <= 1.0) bgimg.alpha = alpha;
+	if (bgimg.bgimg == NULL) return;
+	if (bgimg.bgbmp) delete bgimg.bgbmp;
+	bgimg.bgbmp = new wxBitmap(*bgimg.bgimg);
+    PixelData data(*bgimg.bgbmp);
+    wxAlphaPixelFormat::ChannelType* pd = (wxAlphaPixelFormat::ChannelType*) &data.GetPixels().Data();
+    const int stride = data.GetRowStride();
+    if (stride < 0)
+        pd += (data.GetHeight() - 1) * stride;
+    bgimg.ibuf.attach(pd, data.GetWidth(), data.GetHeight(), stride);
+    
+    // apply alpha
+	rasterizer.reset();
+	unsigned w = bgimg.bgbmp->GetWidth(), h = bgimg.bgbmp->GetHeight();
+	bgimg.bg_path = agghelper::RectanglePath(0, w, 0, h);
+    agg::conv_contour< agg::path_storage > cont(bgimg.bg_path);
+	rasterizer.add_path(cont);
+	PixelFormat::AGGType pxt(bgimg.ibuf);
+	RendererBase rpxt(pxt);
+	agg::render_scanlines_aa_solid(rasterizer, scanline, rpxt, agg::rgba(color_bg.r / 255.0, color_bg.g / 255.0, color_bg.b / 255.0, bgimg.alpha));
+}
+
+void ASSDrawCanvas::UpdateBackgroundImgScalePosition(bool firsttime)
+{
+	if (bgimg.bgbmp == NULL) return;
+	// transform the enclosing polygon
+	unsigned w = bgimg.bgbmp->GetWidth(), h = bgimg.bgbmp->GetHeight();
+	bgimg.bg_path = agghelper::RectanglePath(0, w, 0, h);
+    // linear interpolation on image buffer
+    wxRealPoint center, disp;
+    double scale;
+    if (firsttime) // first time
+    {
+	    bgimg.img_mtx = agg::trans_affine();
+	    scale = 1.0;
+		center = wxRealPoint(0.0, 0.0);
+	    disp = wxRealPoint(0.0, 0.0);
+	    bgimg.path_mtx = bgimg.img_mtx;
+	}
+	else
+	{
+		wxRealPoint d_disp(bgimg.new_disp.x - bgimg.disp.x, bgimg.new_disp.y - bgimg.disp.y);
+		scale = bgimg.new_scale;
+		disp = bgimg.disp;
+		center = bgimg.new_center;
+		if (bgimg.scale == scale)
+		{
+		    bgimg.img_mtx.invert();
+		    bgimg.img_mtx *= agg::trans_affine_translation(d_disp.x, d_disp.y);
+			d_disp.x /= scale;
+			d_disp.y /= scale;
+		}
+		else
+		{
+			d_disp.x /= scale;
+			d_disp.y /= scale;
+		    bgimg.img_mtx = agg::trans_affine();
+			disp.x += (center.x - bgimg.center.x) * (1.0 - 1.0 / bgimg.scale);
+			disp.y += (center.y - bgimg.center.y) * (1.0 - 1.0 / bgimg.scale);
+		    bgimg.img_mtx *= agg::trans_affine_translation(-center.x + disp.x, -center.y + disp.y);
+		    bgimg.img_mtx *= agg::trans_affine_scaling(scale);
+		    bgimg.img_mtx *= agg::trans_affine_translation(center.x + d_disp.x, center.y + d_disp.y);
+		}
+	    bgimg.path_mtx = bgimg.img_mtx;
+	    bgimg.img_mtx.invert();
+	    disp.x += d_disp.x;
+	    disp.y += d_disp.y;
+	}
+    //update
+    bgimg.scale = scale;
+    bgimg.center = center;
+    bgimg.disp = disp;
+    bgimg.new_scale = scale;
+    bgimg.new_center = center;
+    bgimg.new_disp = disp;
+}
+
+bool ASSDrawCanvas::GetBackgroundInfo(unsigned& w, unsigned& h, wxRealPoint& disp, double& scale)
+{
+	if (!HasBackgroundImage()) return false;
+	w = bgimg.bgbmp->GetWidth(), h = bgimg.bgbmp->GetHeight();
+	double t, l;
+	agg::conv_transform<agg::path_storage, agg::trans_affine> trr(bgimg.bg_path, bgimg.path_mtx);
+	trr.rewind(0);
+	trr.vertex(&l, &t);
+	disp = wxRealPoint(l, t);
+	scale = bgimg.scale;
+	return true;
+}
+
+void ASSDrawCanvas::UpdateNonUniformTransformation()
+{
+	double bound[8] = {
+		rectbound2[0].x, rectbound2[0].y,
+		rectbound2[1].x, rectbound2[1].y,
+		rectbound2[2].x, rectbound2[2].y,
+		rectbound2[3].x, rectbound2[3].y };
+	agg::path_storage trans;
+	unsigned vertices = backupcmds.total_vertices();
+	double x, y;
+	
+	//if (draw_mode == MODE_NUT_BILINEAR)
+	//{
+		agg::trans_bilinear trans_b(rectbound[0].x, rectbound[0].y, rectbound[2].x, rectbound[2].y, bound);
+		agg::conv_transform<agg::path_storage, agg::trans_bilinear> transb(backupcmds, trans_b);
+		transb.rewind(0);
+		for (int i = 0; i < vertices; i++)
+		{
+			transb.vertex(&x, &y);
+			trans.move_to(x, y);
+		}
+	//}
+	/*	else
+	{
+		agg::trans_perspective trans_p(rectbound[0].x, rectbound[0].y, rectbound[2].x, rectbound[2].y, bound);
+		agg::conv_transform<agg::path_storage, agg::trans_perspective> transp(backupcmds, trans_p);
+		transp.rewind(0);
+		for (int i = 0; i < vertices; i++)
+		{
+			transp.vertex(&x, &y);
+			trans.move_to(x, y);
+		}
+	}
+	*/
+	trans.rewind(0);
+	for (DrawCmdList::iterator iterate = cmds.begin(); iterate != cmds.end(); iterate++)
+	{
+		DrawCmd* cmd = (*iterate);
+		for (PointList::iterator iterate2 = cmd->controlpoints.begin(); iterate2 != cmd->controlpoints.end(); iterate2++)
+		{
+	        double x, y;
+	        trans.vertex(&x, &y);
+	        int wx, wy;
+			pointsys->FromWxPoint ( wxPoint((int)x, (int)y), wx, wy );
+			(*iterate2)->setXY(wx, wy);
+		}
+	    double x, y;
+	    trans.vertex(&x, &y);
+	    int wx, wy;
+		pointsys->FromWxPoint ( wxPoint((int)x, (int)y), wx, wy );
+		(*iterate)->m_point->setXY(wx, wy);
+	}
+	
+}
+
+void ASSDrawCanvas::CustomOnKeyDown(wxKeyEvent &event)
+{
+	int keycode = event.GetKeyCode();
+	//m_frame->SetStatusText(wxString::Format("Key: %d", keycode));
+	double scrollamount = (event.GetModifiers() == wxMOD_CMD? 10.0:1.0);	
+    if (event.GetModifiers() == wxMOD_SHIFT)
+	{
+		MODE d_mode = GetDrawMode();
+        if ((int) d_mode > (int) MODE_ARR && (int) d_mode < (int) MODE_SCALEROTATE)
+		{
+			mode_b4_shift = d_mode;
+			SetDrawMode( MODE_ARR );
+			m_frame->UpdateFrameUI();
+		}
+    }
+    else
+    {
+		switch (keycode)
+		{
+		case WXK_PAGEUP:
+			ChangeZoomLevel( 1.0 /scrollamount, wxPoint( (int) pointsys->originx, (int) pointsys->originy ) );
+			RefreshDisplay();
+			break;
+		case WXK_PAGEDOWN:
+			ChangeZoomLevel( - 1.0 /scrollamount, wxPoint( (int) pointsys->originx, (int) pointsys->originy ) );
+			RefreshDisplay();
+			break;
+		case WXK_UP:
+			MoveCanvas(0.0, -scrollamount);
+			RefreshDisplay();
+			break;
+		case WXK_DOWN:
+			MoveCanvas(0.0, scrollamount);
+			RefreshDisplay();
+			break;
+		case WXK_LEFT:
+			MoveCanvas(-scrollamount, 0.0);
+			RefreshDisplay();
+			break; 
+		case WXK_RIGHT:
+			MoveCanvas(scrollamount, 0.0);
+			RefreshDisplay();
+			break;
+		case WXK_TAB:
+			if (mousedownAt_point == NULL && !IsTransformMode() && cmds.size() > 0)
+			{
+				if (pointedAt_point == NULL)
+				{
+					Point *nearest = NULL;
+					double dist = 0.0;
+					DrawCmdList::iterator it = cmds.begin();
+					while(it != cmds.end())
+					{
+						wxPoint point = (*it)->m_point->ToWxPoint();
+						double distance = sqrt(pow(point.x - mouse_point.x, 2) + pow(point.y - mouse_point.y, 2));
+						if (nearest == NULL || distance < dist)
+						{
+							nearest = (*it)->m_point;
+							dist = distance;
+						}
+						PointList::iterator it2 = (*it)->controlpoints.begin();
+						while (it2 != (*it)->controlpoints.end())
+						{
+							wxPoint point = (*it2)->ToWxPoint();
+							double distance = sqrt(pow(point.x - mouse_point.x, 2) + pow(point.y - mouse_point.y, 2));
+							if (nearest == NULL || distance < dist)
+							{
+								nearest = (*it2);
+								dist = distance;
+							}						
+							it2++;	
+						}
+						it++;
+					}
+					if (nearest != NULL)
+					{
+						wxPoint point = nearest->ToWxPoint();
+						WarpPointer(point.x, point.y);
+					}
+				}
+				else
+				{
+					Point *warpto = NULL;
+					if (pointedAt_point->type == MP)
+					{
+						if (pointedAt_point->cmd_next != NULL)
+						{
+							if (pointedAt_point->cmd_next->controlpoints.size() > 0)
+								warpto = pointedAt_point->cmd_next->controlpoints.front();
+							else
+								warpto = pointedAt_point->cmd_next->m_point;
+						}
+					}
+					else
+					{
+						PointList::iterator it = pointedAt_point->cmd_main->controlpoints.begin();
+						while (*it != pointedAt_point) it++;
+						it++;
+						if (it == pointedAt_point->cmd_main->controlpoints.end())
+							warpto = pointedAt_point->cmd_main->m_point;
+						else
+							warpto = *it;
+					}
+					if (warpto == NULL)
+						warpto = cmds.front()->m_point;
+					wxPoint point = warpto->ToWxPoint();
+					WarpPointer(point.x, point.y);
+				}
+			}
+			break;
+		default:
+	        event.Skip();
+		}
+	}
+}
+
+void ASSDrawCanvas::CustomOnKeyUp(wxKeyEvent &event)
+{
+	int keycode = event.GetKeyCode();
+	if (event.GetModifiers() != wxMOD_SHIFT && (int) mode_b4_shift > (int) MODE_ARR)
+	{
+		SetDrawMode( mode_b4_shift );
+		m_frame->UpdateFrameUI();
+		mode_b4_shift = MODE_ARR;
+	}
+}
+
+void ASSDrawCanvas::OnAlphaSliderChanged(wxScrollEvent &event)
+{
+	double pos = (double) event.GetPosition();
+	PrepareBackgroundBitmap(1.0 - pos / 100.0);
+	RefreshDisplay();
+}
+
+void ASSDrawCanvas::CustomOnMouseCaptureLost(wxMouseCaptureLostEvent &event)
+{
+	if (capturemouse_left)
+		ProcessOnMouseLeftUp();
+
+	if (capturemouse_right)
+		ProcessOnMouseRightUp();
+}
+
+void UndoRedo::Import(ASSDrawCanvas *canvas, bool prestage, wxString cmds)
+{
+	if (prestage)
+	{
+		this->cmds = cmds;
+		this->backupcmds.free_all();
+		this->backupcmds.concat_path(canvas->backupcmds);
+		for (int i = 0; i < 4; i++)
+		{
+			this->rectbound[i] = canvas->rectbound[i];
+			this->rectbound2[i] = canvas->rectbound2[i];
+			this->backup[i] = canvas->backup[i];
+		}
+		this->isshapetransformable = canvas->isshapetransformable;
+	}
+	else
+	{
+	    this->originx = canvas->pointsys->originx;
+		this->originy = canvas->pointsys->originy;
+	    this->scale = canvas->pointsys->scale;
+	
+		this->bgimgfile = canvas->bgimg.bgimgfile;
+		this->bgdisp = canvas->bgimg.disp;
+		this->bgcenter = canvas->bgimg.center;
+		this->bgscale = canvas->bgimg.scale;
+		this->bgalpha = canvas->bgimg.alpha;
+		this->c1cont = canvas->PrepareC1ContData();
+		this->draw_mode = canvas->draw_mode;
+	}
+}
+
+void UndoRedo::Export(ASSDrawCanvas *canvas)
+{
+	canvas->pointsys->originx = this->originx;
+	canvas->pointsys->originy = this->originy;
+	canvas->pointsys->scale = this->scale;
+	canvas->ParseASS( this->cmds );
+	DrawCmdList::iterator it1 = canvas->cmds.begin();
+	std::vector< bool >::iterator it2 = this->c1cont.begin();
+	for(; it1 != canvas->cmds.end() && it2 != this->c1cont.end(); it1++, it2++)
+		if (*it2 && (*it1)->type == B)
+			static_cast<DrawCmd_B*>(*it1)->C1Cont = true;
+
+	if (canvas->bgimg.bgimgfile != this->bgimgfile)
+	{
+		canvas->RemoveBackgroundImage();
+		if (!this->bgimgfile.IsSameAs("<clipboard>") && ::wxFileExists(this->bgimgfile))
+		{
+			canvas->bgimg.alpha = this->bgalpha;
+			canvas->ReceiveBackgroundImageFileDropEvent(this->bgimgfile);
+		}
+	}
+	else
+	{
+		canvas->bgimg.new_scale = this->bgscale;
+		canvas->bgimg.new_center = this->bgcenter;
+		canvas->bgimg.new_disp = this->bgdisp;
+		canvas->bgimg.alpha = this->bgalpha;
+		canvas->UpdateBackgroundImgScalePosition();
+	}	
+	
+
+	//canvas->SetDrawMode(this->draw_mode);
+	canvas->draw_mode = this->draw_mode;
+	if (canvas->IsTransformMode())
+	{
+		canvas->backupcmds.free_all();
+		canvas->backupcmds.concat_path(this->backupcmds);
+		for (int i = 0; i < 4; i++)
+		{
+			canvas->rectbound[i] = this->rectbound[i];
+			canvas->rectbound2[i] = this->rectbound2[i];
+			canvas->backup[i] = this->backup[i];
+		}
+		canvas->UpdateNonUniformTransformation();
+		canvas->InitiateDraggingIfTransformMode();
+		canvas->rectbound2upd = -1;
+		canvas->rectbound2upd2 = -1;
+		canvas->isshapetransformable = this->isshapetransformable;
+	}
+}
diff --git a/assdraw/src/canvas.hpp b/assdraw/src/canvas.hpp
new file mode 100644
index 000000000..23f4abf4b
--- /dev/null
+++ b/assdraw/src/canvas.hpp
@@ -0,0 +1,303 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        canvas.hpp
+// Purpose:     header file for ASSDraw main canvas class
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <vector>
+
+#include "engine.hpp"
+#include "enums.hpp"
+
+#include <wx/dnd.h>
+#include <wx/splitter.h>
+#include <wx/clntdata.h>
+
+#include "agg_span_allocator.h"
+#include "agg_span_interpolator_linear.h"
+#include "agg_span_image_filter_rgb.h"
+#include "agg_span_image_filter_rgba.h"
+#include "agg_image_accessors.h"
+#include "agg_conv_clip_polygon.h"
+
+class ASSDrawFrame;
+class ASSDrawCanvas;
+
+struct UndoRedo
+{
+	wxString cmds;
+	wxString desc;
+	double originx, originy, scale;
+
+	std::vector< bool > c1cont;
+	wxString bgimgfile;
+	wxRealPoint bgdisp, bgcenter;
+	double bgscale, bgalpha;
+
+	MODE draw_mode;
+	agg::path_storage backupcmds;
+	wxRealPoint rectbound[4], rectbound2[4], backup[4];
+	bool isshapetransformable;
+
+	void Import(ASSDrawCanvas *canvas, bool prestage, wxString cmds = _T(""));
+	void Export(ASSDrawCanvas *canvas);
+	
+};
+
+// for multiple point selection
+enum SELECTMODE { NEW, ADD, DEL };
+
+class ASSDrawCanvas: public ASSDrawEngine, public wxClientData
+{
+public:
+	ASSDrawCanvas( wxWindow *parent, ASSDrawFrame *frame, int extraflags = 0 );
+
+    // destructor
+    ~ASSDrawCanvas();
+
+    virtual void ResetEngine(bool addM);
+	virtual void SetPreviewMode( bool mode );
+	virtual bool IsPreviewMode() { return preview_mode; }
+	virtual void ParseASS(wxString str, bool addundo = false);
+
+	virtual void SetDrawMode( MODE mode );
+	virtual MODE GetDrawMode() { return draw_mode; }
+	virtual bool IsTransformMode();
+	virtual void SetDragMode( DRAGMODE mode );
+	virtual DRAGMODE GetDragMode() { return drag_mode; }
+	virtual void RefreshDisplay();
+	virtual bool CanZoom();
+	virtual bool CanMove();
+	
+    virtual void OnMouseMove(wxMouseEvent &event);
+    virtual void OnMouseLeftUp(wxMouseEvent &event);
+    virtual void OnMouseLeftDown(wxMouseEvent &event);
+    virtual void OnMouseRightUp(wxMouseEvent &event);
+    virtual void OnMouseRightDown(wxMouseEvent &event);
+    virtual void OnMouseRightDClick(wxMouseEvent &event);
+    virtual void OnMouseWheel(wxMouseEvent &event);
+    virtual void CustomOnKeyDown(wxKeyEvent &event);
+    virtual void CustomOnKeyUp(wxKeyEvent &event);
+	virtual void ChangeZoomLevel(double zoomamount, wxPoint bgzoomctr);
+	virtual void ChangeZoomLevelTo(double zoom, wxPoint bgzoomctr);
+	virtual void ChangeDrawingZoomLevel(double zoom);
+	virtual void ChangeBackgroundZoomLevel(double zoom, wxRealPoint newcenter);
+	virtual void MoveCanvas(double xamount, double yamount);
+	virtual void MoveCanvasOriginTo(double originx, double originy);
+	virtual void MoveCanvasDrawing(double xamount, double yamount);
+	virtual void MoveCanvasBackground(double xamount, double yamount);
+	virtual void OnSelect_ConvertLineToBezier(wxCommandEvent& WXUNUSED(event));
+	virtual void OnSelect_ConvertBezierToLine(wxCommandEvent& WXUNUSED(event));
+	virtual void OnSelect_C1ContinuityBezier(wxCommandEvent& WXUNUSED(event));
+	virtual void OnSelect_Move00Here(wxCommandEvent& WXUNUSED(event));
+	void OnAlphaSliderChanged(wxScrollEvent &event);
+	
+	// to replace _PointSystem() that has been made protected
+	double GetScale() { return pointsys->scale; }
+	double GetOriginX() { return pointsys->originx; }
+	double GetOriginY() { return pointsys->originy; }
+
+	// undo/redo system
+	virtual void AddUndo( wxString desc );
+	virtual bool UndoOrRedo(bool isundo);
+	virtual bool Undo();
+	virtual bool Redo();
+	virtual wxString GetTopUndo();
+	virtual wxString GetTopRedo();
+	virtual void RefreshUndocmds();
+
+	virtual bool HasBackgroundImage() { return bgimg.bgimg != NULL; }
+	virtual void RemoveBackgroundImage();
+	virtual void ReceiveBackgroundImageFileDropEvent(const wxString& filename);
+	virtual void SetBackgroundImage(const wxImage& img, wxString fname = _T("<clipboard>"), bool ask4alpha = true);
+	virtual void PrepareBackgroundBitmap(double alpha);
+	virtual void AskUserForBackgroundAlpha();
+	virtual bool GetBackgroundInfo(unsigned& w, unsigned& h, wxRealPoint& disp, double& scale);
+	
+	agg::rgba rgba_shape_normal, rgba_outline, rgba_guideline;
+	agg::rgba rgba_mainpoint, rgba_controlpoint, rgba_selectpoint;
+	agg::rgba rgba_origin, rgba_ruler_h, rgba_ruler_v;
+	
+protected:
+
+	typedef PixelFormat::AGGType::color_type color_type;
+	typedef agg::span_interpolator_linear<> interpolator_type;
+	typedef agg::span_image_filter_rgb_bilinear_clip<PixelFormat::AGGType, interpolator_type> span_gen_type;
+	
+    // The GUI window
+	ASSDrawFrame* m_frame;
+
+	// highlight mechanism
+	DrawCmd* hilite_cmd;
+	Point* hilite_point;
+		
+	// mouse capture
+	bool capturemouse_left, capturemouse_right;
+	virtual void CustomOnMouseCaptureLost(wxMouseCaptureLostEvent &event);
+    virtual void ProcessOnMouseLeftUp();
+    virtual void ProcessOnMouseRightUp();
+
+	// selection mechanism
+	PointSet selected_points;
+
+	// if it has status bar
+	bool hasStatusBar;
+
+	// some mouse readings
+    Point* mousedownAt_point;
+	Point* pointedAt_point;
+	Point* dblclicked_point_right;
+	wxPoint mouse_point;
+
+	// The wxPoint being dragged by left button
+    wxPoint* dragAnchor_left;
+	wxPoint* lastDrag_left;
+
+	// The wxPoint being dragged by right button
+    wxPoint* dragAnchor_right;
+	wxPoint* lastDrag_right;
+	
+	// true if the drawing origin (0, 0) is being dragged
+    bool dragOrigin;
+
+	// The newest command being initialized thru dragging action
+    DrawCmd* newcommand;
+
+	// the draw mode
+    MODE draw_mode;
+    DRAGMODE drag_mode;
+
+    // holding shift key temporarily switches to drag mode (MODE_ARR)
+    // so we want to save the mode before the key-down to restore it on key-up
+    MODE mode_b4_shift;
+
+	// true if preview mode (i.e don't draw anything except the shape itself;
+    // also draw the shape as closed)
+    bool preview_mode;
+
+	// background image!
+	struct
+	{
+		agg::rendering_buffer ibuf;
+		wxImage *bgimg;
+		wxBitmap *bgbmp;
+		wxString bgimgfile;
+		agg::path_storage bg_path;		
+		agg::span_allocator<color_type> spanalloc;
+		//span_gen_type spangen;
+        agg::trans_affine img_mtx, path_mtx;
+        
+        wxRealPoint disp, center, new_disp, new_center;
+        double scale, new_scale, alpha;
+		wxDialog* alpha_dlg;
+		wxSlider* alpha_slider;
+	} bgimg;
+	
+	// Undo/redo system (simply stores the ASS commands)
+	std::list<UndoRedo> undos;
+	std::list<UndoRedo> redos;
+	UndoRedo _undo;
+
+	// last action and commands (for undo/redo system)
+	wxString undodesc;
+	
+	wxString oldasscmds;
+
+	// was preview_mode
+	//bool was_preview_mode;
+
+	PointSystem* _PointSystem() { return pointsys; }
+
+	// for Undo/Redo system
+	virtual void PrepareUndoRedo(UndoRedo& ur, bool prestage, wxString cmds, wxString desc);
+	
+	// -------------------- points highlight/selection ---------------------------
+
+	// set command and point to highlight
+	virtual void SetHighlighted ( DrawCmd* cmd, Point* point );
+
+	// selects all points within (lx, ty) , (rx, by) returns # of selected points
+	virtual int SelectPointsWithin( int lx, int rx, int ty, int by, SELECTMODE smode = NEW );
+	virtual void ClearPointsSelection();
+	virtual SELECTMODE GetSelectMode(wxMouseEvent &event);
+	
+	// -------------------- misc ---------------------------
+
+	// non-uniform transformation
+	virtual bool InitiateDraggingIfTransformMode();
+	virtual void UpdateTranformModeRectCenter();
+	virtual bool GetThe4thPoint(double ox, double oy, double a1x, double a1y, double a2x, double a2y, double *x, double *y);
+	enum { NONE, LEFT, RIGHT } backupowner;
+	agg::path_storage backupcmds;
+	int rectbound2upd, rectbound2upd2;
+	wxRealPoint rectbound[4], rectbound2[4], backup[4], rectcenter;
+	bool isshapetransformable;
+
+	// do the real drawing
+	virtual void DoDraw( RendererBase& rbase, RendererPrimitives& rprim, RendererSolid& rsolid, agg::trans_affine& mtx );
+
+	// update background image scale & position
+	virtual void UpdateBackgroundImgScalePosition(bool firsttime = false);
+	
+	// perform extra stuff other than calling ASSDrawEngine::ConnectSubsequentCmds
+	virtual void ConnectSubsequentCmds (DrawCmd* cmd1, DrawCmd* cmd2);
+
+	// make sure the c1 continuity is followed after performing a drag-point action
+	virtual void EnforceC1Continuity (DrawCmd* cmd, Point* pnt);
+	
+	// after the bounding quadrangle has changed, update the shape to fill up inside it
+	virtual void UpdateNonUniformTransformation();
+
+	friend class UndoRedo;
+	
+	DECLARE_EVENT_TABLE()
+};
+
+class ASSDrawFileDropTarget : public wxFileDropTarget
+{
+public:
+	ASSDrawFileDropTarget(ASSDrawCanvas *canvas): wxFileDropTarget()
+	{
+		m_canvas = canvas;
+	}
+
+	virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
+	{
+		m_canvas->ReceiveBackgroundImageFileDropEvent(filenames.Item(0));
+	}
+
+protected:
+	ASSDrawCanvas *m_canvas;
+
+};
diff --git a/assdraw/src/canvas_mouse.cpp b/assdraw/src/canvas_mouse.cpp
new file mode 100644
index 000000000..22b64a5f4
--- /dev/null
+++ b/assdraw/src/canvas_mouse.cpp
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "canvas_mouse.hpp"
+#include "canvas.hpp"
+
+DEFINE_EVENT_TYPE( wxEVT_MOUSEONCANVAS )
+
+
+ASSDrawMouseOnCanvasEvent::ASSDrawMouseOnCanvasEvent(const ASSDrawCanvas* canvas)
+ : wxNotifyEvent(),
+   _canvas(canvas)
+{
+	_data = NULL;
+}
+
+wxEvent* ASSDrawMouseOnCanvasEvent::Clone()
+{
+	ASSDrawMouseOnCanvasEvent *clone = new ASSDrawMouseOnCanvasEvent(_canvas);
+	clone->SetData(_data);
+	return clone;
+}
+
+void ASSDrawMouseOnCanvasEvent::SetData(MouseOnCanvasData *data)
+{
+	_data = data;
+}
+
+MouseOnCanvasData* ASSDrawMouseOnCanvasEvent::GetData()
+{
+	return _data;
+}
diff --git a/assdraw/src/canvas_mouse.hpp b/assdraw/src/canvas_mouse.hpp
new file mode 100644
index 000000000..d64011336
--- /dev/null
+++ b/assdraw/src/canvas_mouse.hpp
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#pragma once
+
+#include "_common.hpp"
+#include "enums.hpp"
+#include "engine.hpp"
+
+#include <wx/event.h>
+
+struct MouseOnCanvasData
+{
+	MODE mode;
+	wxMouseEvent event;
+	enum { NONE, LEFT, RIGHT, BOTH } button;
+
+    Point* mousedownAt_point;
+	Point* pointedAt_point;
+	Point* dblclicked_point_right;
+
+	wxPoint mouse_point;
+    wxPoint* dragAnchor_left;
+	wxPoint* lastDrag_left;
+    wxPoint* dragAnchor_right;
+	wxPoint* lastDrag_right;
+};
+
+class ASSDrawCanvas;
+
+class ASSDrawMouseOnCanvasEvent : public wxNotifyEvent
+{
+public:
+	ASSDrawMouseOnCanvasEvent(const ASSDrawCanvas* canvas);
+	
+	wxEvent* Clone();
+	
+	void SetData(MouseOnCanvasData *data);
+	
+	MouseOnCanvasData* GetData();
+	
+private:
+	const ASSDrawCanvas* _canvas;
+	MouseOnCanvasData* _data;
+
+};
+
+DECLARE_EVENT_TYPE( wxEVT_MOUSEONCANVAS, -1 )
+
+typedef void (wxEvtHandler::*wxMouseOnCanvasEventFunction)(ASSDrawMouseOnCanvasEvent&);
+
+#define EVT_MOUSEONCANVAS(fn) \
+    DECLARE_EVENT_TABLE_ENTRY( wxEVT_MOUSEONCANVAS, -1, -1, \
+    (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) \
+    wxStaticCastEvent( wxMouseOnCanvasEventFunction, & fn ), (wxObject *) NULL ),
+
+class ASSDrawMouseOnCanvasHandler
+{
+	
+	
+};
diff --git a/assdraw/src/cmd.cpp b/assdraw/src/cmd.cpp
new file mode 100644
index 000000000..5c3ee3eee
--- /dev/null
+++ b/assdraw/src/cmd.cpp
@@ -0,0 +1,212 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        cmd.cpp
+// Purpose:     ASSDraw drawing command classes
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#include "cmd.hpp" // the header for this file
+#include <wx/log.h>
+// ----------------------------------------------------------------------------
+// DrawCmd_M
+// ----------------------------------------------------------------------------
+
+// constructor
+DrawCmd_M::DrawCmd_M ( int x, int y, PointSystem *ps, DrawCmd *prev ) 
+     : DrawCmd ( x, y, ps, prev ) 
+{
+     type = M;
+}
+
+// to ASS drawing command
+wxString DrawCmd_M::ToString()
+{
+     return wxString::Format(_T("m %d %d"), m_point->x(), m_point->y());
+}
+
+
+
+// ----------------------------------------------------------------------------
+// DrawCmd_L
+// ----------------------------------------------------------------------------
+
+// constructor
+DrawCmd_L::DrawCmd_L ( int x, int y, PointSystem *ps, DrawCmd *prev ) 
+     : DrawCmd ( x, y, ps, prev ) 
+{
+     type = L;
+}
+
+// to ASS drawing command
+wxString DrawCmd_L::ToString()
+{
+     return wxString::Format(wxT("l %d %d"), m_point->x(), m_point->y());
+}
+
+
+
+// ----------------------------------------------------------------------------
+// DrawCmd_B
+// ----------------------------------------------------------------------------
+
+// constructor
+DrawCmd_B::DrawCmd_B 
+( int x, int y, int x1, int y1, int x2, int y2, PointSystem *ps, DrawCmd *prev ) 
+    : DrawCmd ( x, y, ps, prev ) 
+{
+     type = B;
+     controlpoints.push_back( new Point(x1, y1, ps, CP, this, 1) );
+     controlpoints.push_back( new Point(x2, y2, ps, CP, this, 2) );
+     initialized = true;
+     C1Cont = false;
+}
+
+// constructor
+DrawCmd_B::DrawCmd_B ( int x, int y, PointSystem *ps, DrawCmd *prev ) 
+    : DrawCmd ( x, y, ps, prev ) 
+{
+     type = B;
+     initialized = false;
+     C1Cont = false;
+}
+
+// initialize; generate control points
+void DrawCmd_B::Init ( unsigned n )
+{
+     // Ignore if this is already initted
+     if (initialized) return;
+
+     wxPoint wx0 = prev->m_point->ToWxPoint();
+     wxPoint wx1 = m_point->ToWxPoint();
+     int xdiff = (wx1.x - wx0.x) / 3;     
+     int ydiff = (wx1.y - wx0.y) / 3;     
+     int xg, yg;
+
+     // first control
+     m_point->pointsys->FromWxPoint( wx0.x + xdiff, wx0.y + ydiff, xg, yg );
+     controlpoints.push_back( new Point( xg, yg, m_point->pointsys, CP, this, 1 ) );
+
+     // second control
+     m_point->pointsys->FromWxPoint( wx1.x - xdiff, wx1.y - ydiff, xg, yg );
+     controlpoints.push_back( new Point( xg, yg, m_point->pointsys, CP, this, 2 ) );
+
+     initialized = true;
+     
+}
+
+// to ASS drawing command
+wxString DrawCmd_B::ToString()
+{
+	PointList::iterator iterate = controlpoints.begin();
+	Point* c1 = (*iterate++);
+	Point* c2 = (*iterate);
+	if (initialized)
+		return wxString::Format(wxT("b %d %d %d %d %d %d"), c1->x(), c1->y(), c2->x(), c2->y(), m_point->x(), m_point->y());
+	else
+		return wxString::Format(wxT("b ? ? ? ? %d %d"), m_point->x(), m_point->y());
+}
+
+
+// ----------------------------------------------------------------------------
+// DrawCmd_S
+// ----------------------------------------------------------------------------
+
+// constructor
+DrawCmd_S::DrawCmd_S
+	( int x, int y, PointSystem *ps, DrawCmd *prev )
+    : DrawCmd ( x, y, ps, prev )
+{
+	type = S;
+	initialized = false;
+	closed = false;
+}
+
+// constructor
+DrawCmd_S::DrawCmd_S
+	( int x, int y, std::vector< int > vals, PointSystem *ps, DrawCmd *prev )
+    : DrawCmd ( x, y, ps, prev )
+{
+	type = S;
+	std::vector< int >::iterator it = vals.begin();
+	unsigned n = 0;
+	while (it != vals.end())
+	{
+		int ix = *it; it++;
+		int iy = *it; it++;
+		n++;
+		//::wxLogMessage("%d %d\n", ix, iy);
+		controlpoints.push_back( new Point( ix, iy, ps, CP, this, n ) );
+	}
+
+	initialized = true;
+	closed = false;
+}
+
+// initialize; generate control points
+void DrawCmd_S::Init(unsigned n)
+{
+     // Ignore if this is already initted
+     if (initialized) return;
+
+     wxPoint wx0 = prev->m_point->ToWxPoint();
+     wxPoint wx1 = m_point->ToWxPoint();
+     int xdiff = (wx1.x - wx0.x) / 3;
+     int ydiff = (wx1.y - wx0.y) / 3;
+     int xg, yg;
+
+     // first control
+     m_point->pointsys->FromWxPoint( wx0.x + xdiff, wx0.y + ydiff, xg, yg );
+     controlpoints.push_back( new Point( xg, yg, m_point->pointsys, CP, this, 1 ) );
+
+     // second control
+     m_point->pointsys->FromWxPoint( wx1.x - xdiff, wx1.y - ydiff, xg, yg );
+     controlpoints.push_back( new Point( xg, yg, m_point->pointsys, CP, this, 2 ) );
+
+     initialized = true;
+
+}
+
+// to ASS drawing command
+wxString DrawCmd_S::ToString()
+{
+	PointList::iterator iterate = controlpoints.begin();
+	wxString assout = _T("s");
+	for (; iterate != controlpoints.end(); iterate++)
+	{
+		if (initialized)
+			assout = wxString::Format(wxT("%s %d %d"), assout.c_str(), (*iterate)->x(), (*iterate)->y()); 
+		else
+			assout = wxString::Format(wxT("%s ? ?"), assout.c_str());
+	}
+	assout = wxString::Format(wxT("%s %d %d"), assout.c_str(), m_point->x(), m_point->y());
+	if (closed) assout = wxString::Format(wxT("%s c"), assout.c_str());
+	return assout;
+}
diff --git a/assdraw/src/cmd.hpp b/assdraw/src/cmd.hpp
new file mode 100644
index 000000000..25ef16102
--- /dev/null
+++ b/assdraw/src/cmd.hpp
@@ -0,0 +1,112 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// Name:        cmd.hpp
+// Purpose:     header file for ASSDraw drawing command classes
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include "engine.hpp" // include the engine header for DrawCmd
+#include <vector> // ok, we use vector too
+
+// this header file declares the following classes
+class DrawCmd_M;
+class DrawCmd_L;
+class DrawCmd_B;
+
+// The M command
+class DrawCmd_M: public DrawCmd
+{
+public:
+	// Constructor
+	DrawCmd_M ( int x, int y, PointSystem *ps, DrawCmd *prev );
+	
+	// to ASS drawing command
+	wxString ToString();
+
+};
+
+// The L command
+class DrawCmd_L: public DrawCmd
+{
+public:
+	// Constructor
+	DrawCmd_L ( int x, int y, PointSystem *ps, DrawCmd *prev );
+	
+	// to ASS drawing command
+	wxString ToString();
+	
+};
+
+// The B command
+class DrawCmd_B: public DrawCmd
+{
+public:
+	// Constructor
+	DrawCmd_B ( int x, int y, int x1, int y1, int x2, int y2,  PointSystem *ps, DrawCmd *prev );
+	
+	// Special constructor where only m_point is defined
+	// Need to call Init() to generate the controls
+	DrawCmd_B ( int x, int y, PointSystem *ps, DrawCmd *prev );
+	
+	// Init this B command; generate controlpoints
+	void Init ( unsigned n = 0 );
+	
+	// to ASS drawing command
+	wxString ToString();
+	
+	//special
+	bool C1Cont;
+	
+};
+
+// The S command
+class DrawCmd_S: public DrawCmd
+{
+public:
+	// Constructor
+	DrawCmd_S ( int x, int y, PointSystem *ps, DrawCmd *prev );
+
+	// Constructor (with points info)
+	DrawCmd_S ( int x, int y, std::vector< int > vals, PointSystem *ps, DrawCmd *prev );
+
+	// Init this S command; generate controlpoints
+	void Init ( unsigned n = 0 );
+
+	// to ASS drawing command
+	wxString ToString();
+
+	// special
+	bool closed;
+};
+
diff --git a/assdraw/src/dlgctrl.cpp b/assdraw/src/dlgctrl.cpp
new file mode 100644
index 000000000..1ee6f9b89
--- /dev/null
+++ b/assdraw/src/dlgctrl.cpp
@@ -0,0 +1,372 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        dlgctrl.cpp
+// Purpose:     custom dialogs and controls
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#include "assdraw.hpp"
+
+BEGIN_EVENT_TABLE(ASSDrawSrcTxtCtrl, wxTextCtrl)
+	EVT_CHAR(ASSDrawSrcTxtCtrl::CustomOnChar)
+	EVT_TEXT(wxID_ANY, ASSDrawSrcTxtCtrl::CustomOnText)
+END_EVENT_TABLE()
+
+BEGIN_EVENT_TABLE(ASSDrawTransformDlg, wxDialog)
+	EVT_COMBOBOX(-1, ASSDrawTransformDlg::OnTemplatesCombo)
+END_EVENT_TABLE()
+
+//BEGIN_EVENT_TABLE(ASSDrawCanvasRecenterButton, wxWindow)
+//END_EVENT_TABLE()
+
+// ----------------------------------------------------------------------------
+// ASSDrawSrcTxtCtrl
+// ----------------------------------------------------------------------------
+
+ASSDrawSrcTxtCtrl::ASSDrawSrcTxtCtrl(wxWindow *parent, ASSDrawFrame *frame)
+	: wxTextCtrl(parent, wxID_ANY, "", __DPDS__ , wxTE_MULTILINE )
+{
+	m_frame = frame;
+}
+
+void ASSDrawSrcTxtCtrl::CustomOnChar(wxKeyEvent &event)
+{
+	switch (event.GetKeyCode())
+	{
+	case WXK_RETURN:
+		m_frame->UpdateASSCommandStringFromSrcTxtCtrl(GetValue());
+		break;
+	case WXK_TAB:
+		break; //do nothing
+	default:
+		//m_frame->SetTitle(wxString::Format("Key: %d", event.GetKeyCode()));
+		event.Skip(true);
+	}
+	
+	//SetBackgroundColour(IsModified()? wxColour(0xFF, 0xFF, 0x99):*wxWHITE);
+}
+
+void ASSDrawSrcTxtCtrl::CustomOnText(wxCommandEvent &event)
+{
+	//SetBackgroundColour(IsModified()? wxColour(0xFF, 0xFF, 0x99):*wxWHITE);
+}
+
+// ----------------------------------------------------------------------------
+// ASSDrawTransformDlg
+// ----------------------------------------------------------------------------
+
+ASSDrawTransformDlg::ASSDrawTransformDlg(ASSDrawFrame* parent)
+ : wxDialog(parent, -1, wxString(_T("Transform")))
+{
+	m_frame = parent;
+
+    wxBoxSizer* sizer_main = new wxBoxSizer(wxVERTICAL);
+    this->SetSizer(sizer_main);
+
+    wxBoxSizer* sizer_templates = new wxBoxSizer(wxHORIZONTAL);
+    sizer_main->Add(sizer_templates, 0, wxGROW|wxLEFT, 5);
+
+    sizer_templates->Add(new wxStaticText( this, -1, _("Templates"), __DPDS__ , 0 ),
+						0, wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
+
+    combo_templates = new wxComboBox( this, -1, combo_templatesStrings[0], __DPDS__ , 10, combo_templatesStrings, wxCB_READONLY );
+    sizer_templates->Add(combo_templates, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxFlexGridSizer* sizer_fields = new wxFlexGridSizer(3, 4, 0, 0);
+    sizer_main->Add(sizer_fields, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT, 5);
+
+	int flag_txtctrl = wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL;
+	int flag_statictxt = wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE;
+
+	sizer_fields->Add(new wxStaticText( this, -1, _("m11"), __DPDS__ , 0 ),
+						0, flag_statictxt, 5);
+
+    txtctrl_m11 = new wxTextCtrl( this, -1, _T("1.0"), __DPDS__ , wxTE_RIGHT );
+    sizer_fields->Add(txtctrl_m11, 0, flag_txtctrl, 5);
+
+    sizer_fields->Add(new wxStaticText( this, -1, _("m12"), __DPDS__ , 0 ),
+						0, flag_statictxt, 5);
+
+    txtctrl_m12 = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
+    sizer_fields->Add(txtctrl_m12, 0, flag_txtctrl, 5);
+
+    sizer_fields->Add(new wxStaticText( this, -1, _("m21"), __DPDS__ , 0 ),
+						0, flag_statictxt, 5);
+
+    txtctrl_m21 = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
+    sizer_fields->Add(txtctrl_m21, 0, flag_txtctrl, 5);
+
+    sizer_fields->Add(new wxStaticText( this, -1, _("m22"), __DPDS__ , 0 ),
+						0, flag_statictxt, 5);
+
+    txtctrl_m22 = new wxTextCtrl( this, -1, _T("1.0"), __DPDS__ , wxTE_RIGHT );
+    sizer_fields->Add(txtctrl_m22, 0, flag_txtctrl, 5);
+
+    sizer_fields->Add(new wxStaticText( this, -1, _("mx"), __DPDS__ , 0 ),
+						0, flag_statictxt, 5);
+
+    txtctrl_mx = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
+    sizer_fields->Add(txtctrl_mx, 0, flag_txtctrl, 5);
+
+    sizer_fields->Add(new wxStaticText( this, -1, _("my"), __DPDS__ , 0 ),
+						0, flag_statictxt, 5);
+
+    txtctrl_my = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
+    sizer_fields->Add(txtctrl_my, 0, flag_txtctrl, 5);
+
+    sizer_fields->Add(new wxStaticText( this, -1, _("nx"), __DPDS__ , 0 ),
+						0, flag_statictxt, 5);
+
+    txtctrl_nx = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
+    sizer_fields->Add(txtctrl_nx, 0, flag_txtctrl, 5);
+
+    sizer_fields->Add(new wxStaticText( this, -1, _("ny"), __DPDS__ , 0 ),
+						0, flag_statictxt, 5);
+
+    txtctrl_ny = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
+    sizer_fields->Add(txtctrl_ny, 0, flag_txtctrl, 5);
+
+    wxBitmap staticbmp_bmp(wxBITMAP(transform));
+    wxStaticBitmap* staticbmp = new wxStaticBitmap( this, -1, staticbmp_bmp, wxDefaultPosition, wxSize(224, 56), 0 );
+    sizer_main->Add(staticbmp, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+    wxStdDialogButtonSizer* sizer_stdbutt = new wxStdDialogButtonSizer;
+
+    sizer_main->Add(sizer_stdbutt, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+    wxButton* button_ok = new wxButton( this, wxID_OK, _("&OK"), __DPDS__ , 0 );
+    sizer_stdbutt->AddButton(button_ok);
+
+    wxButton* button_cancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), __DPDS__ , 0 );
+    sizer_stdbutt->AddButton(button_cancel);
+
+    sizer_stdbutt->Realize();
+
+	sizer_main->Fit(this);
+
+}
+
+void ASSDrawTransformDlg::OnTemplatesCombo(wxCommandEvent &event)
+{
+	int pos = -1;
+	for (int i = 0; i < combo_templatesCount; i++)
+		if (combo_templatesStrings[i].IsSameAs(((wxComboBox *) event.GetEventObject())->GetValue()))
+		{
+			pos = i;
+			break;
+		}
+	if (pos == -1)
+		return;
+
+	txtctrl_m11->SetValue( wxString::Format("%.1f", combo_templatesValues[pos].f1) );
+	txtctrl_m12->SetValue( wxString::Format("%.1f", combo_templatesValues[pos].f2) );
+	txtctrl_m21->SetValue( wxString::Format("%.1f", combo_templatesValues[pos].f3) );
+	txtctrl_m22->SetValue( wxString::Format("%.1f", combo_templatesValues[pos].f4) );
+	txtctrl_mx->SetValue( wxString::Format("%.1f", combo_templatesValues[pos].f5) );
+	txtctrl_my->SetValue( wxString::Format("%.1f", combo_templatesValues[pos].f6) );
+	txtctrl_nx->SetValue( wxString::Format("%.1f", combo_templatesValues[pos].f7) );
+	txtctrl_ny->SetValue( wxString::Format("%.1f", combo_templatesValues[pos].f8) );
+}
+
+void ASSDrawTransformDlg::EndModal(int retCode)
+{
+	if (retCode != wxID_OK)
+	{
+		wxDialog::EndModal(retCode);
+		return;
+	}
+
+	bool ok = true;
+
+	ok = ok && txtctrl_m11->GetValue().ToDouble( &xformvals.f1 );
+	ok = ok && txtctrl_m12->GetValue().ToDouble( &xformvals.f2 );
+	ok = ok && txtctrl_m21->GetValue().ToDouble( &xformvals.f3 );
+	ok = ok && txtctrl_m22->GetValue().ToDouble( &xformvals.f4 );
+	ok = ok && txtctrl_mx->GetValue().ToDouble( &xformvals.f5 );
+	ok = ok && txtctrl_my->GetValue().ToDouble( &xformvals.f6 );
+	ok = ok && txtctrl_nx->GetValue().ToDouble( &xformvals.f7 );
+	ok = ok && txtctrl_ny->GetValue().ToDouble( &xformvals.f8 );
+
+	if (ok)
+		wxDialog::EndModal(wxID_OK);
+	else
+	    wxMessageBox("One or more values entered are not real numbers.\nPlease fix.", _T("Value error"), wxOK | wxICON_INFORMATION, m_frame);
+
+}
+
+
+ASSDrawAboutDlg::ASSDrawAboutDlg(ASSDrawFrame *parent, unsigned timeout)
+	: wxDialog(parent, wxID_ANY, wxString(TITLE), __DPDS__ , wxSIMPLE_BORDER), time_out(timeout)
+{
+	SetBackgroundColour(*wxWHITE);
+	htmlwin = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxSize(396, 200), wxHW_DEFAULT_STYLE | wxSIMPLE_BORDER);
+	htmlwin->SetPage(
+"<html><body> \
+<p>ASSDraw3 is a tool for designing shapes to be used in ASS subtitle file. \
+<p>To add lines or curves, initiate the draw mode by clicking on the drawing tools. \
+Then, either click on empty space or drag from an existing point to add the new lines/curves. \
+Control points for Bezier curves are generated once you release the mouse button. \
+<p>To modify shapes, drag their points (squares) and control points (circles) in the drag mode. \
+<p><b>Some tips & tricks:</b> \
+<ul> \
+<li> Set background image by dragging image file from explorer onto the canvas \
+<li> Use the Shapes Library to store your drawings \
+<li> Ctrl-Z for undo, Ctrl-Y for redo \
+<li> Use your mousewheel to zoom in/out (PageUp/PageDown keys work too) \
+<li> Dragging with right mouse button moves the drawing and/or background image around. \
+<li> Double clicking with right mouse button for popup menus. \
+<li> Holding shift key while in the draw mode temporarily switches to the drag mode \
+<li> The shapes origin (coordinate [0, 0] depicted by the small cross) is draggable \
+</ul> \
+<p><b>Acknowledgements:</b> \
+<ul> \
+<li> Maxim Shemanarev <a href=\"http://www.antigrain.com\">http://www.antigrain.com</a> for his Anti-Grain Geometry (AGG) graphic toolkit. \
+<li> wxWidgets Project <a href=\"http://www.wxwidgets.org\">http://www.wxwidgets.org</a> for the ultracool GUI toolkit. \
+<li> Adrian Secord <a href=\"http://mrl.nyu.edu/~ajsecord/index.html\">http://mrl.nyu.edu/~ajsecord/index.html</a> for wxAGG, that combines AGG and wxWidgets\
+<li> jfs, ArchMageZeratul, RoRo and everyone at Aegisub's forum <a href=\"http://malakith.net/aegisub\">http://malakith.net/aegisub</a> for all suggestions and supports. \
+</ul> \
+<p>ai-chan recommends Aegisub for all your subtitle and typesetting needs! \
+</body></html>"
+	);	
+	htmlwin->Connect(wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler(ASSDrawAboutDlg::OnURL), NULL, this);
+	
+	wxFlexGridSizer *sizer = new wxFlexGridSizer(1);
+	sizer->AddGrowableCol(0);
+	//sizer->AddGrowableRow(1);
+	
+	sizer->Add(new BigStaticBitmapCtrl(this, wxBITMAP(assdraw3_), *wxWHITE, this), 1, wxEXPAND);
+	sizer->Add(htmlwin, 1, wxLEFT | wxRIGHT, 2);
+	sizer->Add(new wxStaticText(this, wxID_ANY, wxString::Format("Version: %s", VERSION)), 1, wxEXPAND | wxALL, 2);
+	sizer->Add(new wxButton(this, wxID_OK), 0, wxALIGN_CENTER | wxBOTTOM, 10);
+	SetSizer(sizer);
+	sizer->Layout();
+	sizer->Fit(this);
+	
+	Center();
+	//if (CanSetTransparent()) SetTransparent(0xCC);
+	
+	timer.SetOwner(this);
+	Connect(wxEVT_TIMER, wxTimerEventHandler(ASSDrawAboutDlg::OnTimeout));
+	Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(ASSDrawAboutDlg::OnMouseEnterWindow));
+}
+
+ASSDrawAboutDlg::~ASSDrawAboutDlg()
+{
+	timer.Stop();	
+}
+
+int ASSDrawAboutDlg::ShowModal()
+{
+	if (time_out > 0)
+		timer.Start(time_out * 1000, true);
+	wxDialog::ShowModal();
+}
+
+void ASSDrawAboutDlg::OnURL(wxHtmlLinkEvent &event)
+{
+	wxString URL(event.GetLinkInfo().GetHref());
+	if (URL.StartsWith("http://"))
+		::wxLaunchDefaultBrowser(URL);
+	else
+		event.Skip(true);
+}
+
+void ASSDrawAboutDlg::OnTimeout(wxTimerEvent& event)
+{
+	if (IsShown())
+		EndModal(wxID_OK);
+}
+
+void ASSDrawAboutDlg::OnMouseEnterWindow(wxMouseEvent& event)
+{
+	// if mouse enters this dialog, stop the timout timer
+	// and dialog will only close through user input
+	timer.Stop();	
+}
+
+BEGIN_EVENT_TABLE(BigStaticBitmapCtrl, wxPanel)
+	EVT_PAINT(BigStaticBitmapCtrl::OnPaint)
+    EVT_MOTION (BigStaticBitmapCtrl::OnMouseMove)
+    EVT_LEFT_UP(BigStaticBitmapCtrl::OnMouseLeftUp)
+    EVT_LEFT_DOWN(BigStaticBitmapCtrl::OnMouseLeftDown)
+END_EVENT_TABLE()
+
+BigStaticBitmapCtrl::BigStaticBitmapCtrl(wxWindow *parent, wxBitmap bmap, wxColour bgcol, wxWindow *todrag)
+	: wxPanel(parent, wxID_ANY)
+{
+	bitmap = bmap;
+	bgbrush = wxBrush(bgcol);
+	window_to_drag = todrag;
+	SetSize(bitmap.GetWidth(), bitmap.GetHeight());
+	Refresh();
+}
+
+BigStaticBitmapCtrl::~BigStaticBitmapCtrl()
+{	
+}
+
+void BigStaticBitmapCtrl::OnPaint(wxPaintEvent& event)
+{
+    wxPaintDC dc(this);
+	dc.SetBackground(bgbrush);
+	dc.Clear();
+    dc.DrawBitmap(bitmap, wxPoint(0,0));
+}
+
+void BigStaticBitmapCtrl::OnMouseLeftDown(wxMouseEvent &event)
+{
+	if (window_to_drag != NULL)
+	{
+		dragpoint = event.GetPosition();
+	}
+	CaptureMouse();
+}
+
+void BigStaticBitmapCtrl::OnMouseLeftUp(wxMouseEvent &event)
+{
+	ReleaseMouse();	
+}
+
+void BigStaticBitmapCtrl::OnMouseMove(wxMouseEvent &event)
+{
+	if (window_to_drag != NULL && event.Dragging() && HasCapture())
+	{
+		wxPoint npoint(event.GetPosition());
+		wxPoint wndpos = window_to_drag->GetScreenPosition();
+		wxPoint thispos = this->GetScreenPosition();
+		//ReleaseMouse();
+		window_to_drag->Move(wndpos.x + npoint.x - dragpoint.x,
+							 wndpos.y + npoint.y - dragpoint.y);
+		//CaptureMouse();
+		if (thispos == this->GetScreenPosition()) // if this ctrl did not move when window_to_drag moved
+			dragpoint = npoint;
+	}
+	event.Skip(true);
+}
diff --git a/assdraw/src/dlgctrl.hpp b/assdraw/src/dlgctrl.hpp
new file mode 100644
index 000000000..b5225d181
--- /dev/null
+++ b/assdraw/src/dlgctrl.hpp
@@ -0,0 +1,115 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#pragma once
+
+#include "_common.hpp"
+#include <wx/html/htmlwin.h>
+#include <wx/timer.h>
+
+
+class ASSDrawFrame;
+
+class ASSDrawSrcTxtCtrl : public wxTextCtrl
+{
+public:
+	ASSDrawSrcTxtCtrl(wxWindow *parent, ASSDrawFrame *frame);
+	virtual void CustomOnChar(wxKeyEvent &event);
+	virtual void CustomOnText(wxCommandEvent &event);
+
+protected:
+	ASSDrawFrame *m_frame;
+	DECLARE_EVENT_TABLE()
+};
+
+struct EightDouble
+{
+	double f1, f2, f3, f4, f5, f6, f7, f8;
+};
+
+class ASSDrawTransformDlg : public wxDialog
+{
+
+public:
+	ASSDrawTransformDlg(ASSDrawFrame* parent);
+	void OnTemplatesCombo(wxCommandEvent &event);
+	void EndModal(int retCode);
+
+	ASSDrawFrame* m_frame;
+	wxComboBox* combo_templates;
+	wxTextCtrl* txtctrl_m11;
+	wxTextCtrl* txtctrl_m12;
+	wxTextCtrl* txtctrl_m21;
+	wxTextCtrl* txtctrl_m22;
+	wxTextCtrl* txtctrl_mx;
+	wxTextCtrl* txtctrl_my;
+	wxTextCtrl* txtctrl_nx;
+	wxTextCtrl* txtctrl_ny;
+	EightDouble xformvals;
+
+	static wxString combo_templatesStrings[];
+	static int combo_templatesCount;
+	static EightDouble combo_templatesValues[];
+
+	DECLARE_EVENT_TABLE()
+
+};
+
+class ASSDrawAboutDlg : public wxDialog
+{
+public:
+	ASSDrawAboutDlg(ASSDrawFrame *parent, unsigned timeout = 0);
+	virtual ~ASSDrawAboutDlg();
+	virtual void OnURL(wxHtmlLinkEvent &event);
+	virtual int ShowModal();
+	virtual void OnTimeout(wxTimerEvent& event);
+	virtual void OnMouseEnterWindow(wxMouseEvent& event);
+
+protected:
+	wxTimer timer;
+	wxHtmlWindow *htmlwin;
+	const unsigned time_out;
+};
+
+class BigStaticBitmapCtrl : public wxPanel
+{
+public:
+	BigStaticBitmapCtrl(wxWindow *parent, wxBitmap bmap, wxColour bgcol, wxWindow *todrag = NULL);
+	virtual ~BigStaticBitmapCtrl();
+	virtual void OnPaint(wxPaintEvent& event);
+	virtual void OnMouseLeftDown(wxMouseEvent &event);
+	virtual void OnMouseLeftUp(wxMouseEvent &event);
+	virtual void OnMouseMove(wxMouseEvent &event);
+
+protected:
+	wxBitmap bitmap;
+	wxBrush bgbrush;
+	wxWindow *window_to_drag;
+	wxPoint dragpoint, wndpos;
+
+	DECLARE_EVENT_TABLE()
+};
diff --git a/assdraw/src/engine.cpp b/assdraw/src/engine.cpp
new file mode 100644
index 000000000..fa23da684
--- /dev/null
+++ b/assdraw/src/engine.cpp
@@ -0,0 +1,749 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        engine.cpp
+// Purpose:     ASSDraw drawing engine
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#include "engine.hpp" // the header
+#include "cmd.hpp"    // we need the drawing command classes declaration
+#include <wx/tokenzr.h> // we use string tokenizer
+#include <vector> // ok, we use vector too
+#include <stdio.h>
+#include <algorithm>
+
+      
+
+// ----------------------------------------------------------------------------
+// Point
+// ----------------------------------------------------------------------------
+
+// constructor
+Point::Point ( int _x, int _y, PointSystem* ps, POINTTYPE t, DrawCmd* cmd, unsigned n ) 
+{
+	x_ = _x;
+	y_ = _y;
+	pointsys = ps;
+	cmd_main = cmd; 
+	cmd_next = NULL; 
+	type = t;
+	isselected = false;
+	num = n;
+}      
+
+// setters
+void Point::setXY( int _x, int _y)
+{
+	x_ = _x;
+	y_ = _y;
+}
+
+// simply returns true if px and py are the coordinate values
+bool Point::IsAt( int px, int py ) 
+{
+	return (x_ == px && y_ == py );
+}
+      
+// convert this point to wxPoint using scale and originx, originy
+wxPoint Point::ToWxPoint ( bool useorigin )
+{
+	if (useorigin)
+		return pointsys->ToWxPoint( x_, y_ );
+	else
+		return *(new wxPoint(x_ * (int) pointsys->scale, y_ * (int) pointsys->scale ));
+}
+      
+// check if wxpoint is nearby this point
+bool Point::CheckWxPoint ( wxPoint wxpoint ) 
+{
+	wxPoint p = ToWxPoint();
+	int cx, cy;
+	pointsys->FromWxPoint( wxpoint, cx, cy );
+	//delete &p;
+	return (x_ == cx && y_ == cy );
+}
+      
+
+
+// ----------------------------------------------------------------------------
+// DrawCmd
+// ----------------------------------------------------------------------------
+
+// constructor
+DrawCmd::DrawCmd ( int x, int y, PointSystem *ps, DrawCmd *pv ) 
+{ 
+	m_point = new Point ( x, y, ps, MP, this );
+	m_point->cmd_main = this;
+	prev = pv;
+	dobreak = false;
+	invisible = false;
+}       
+
+// destructor
+DrawCmd::~DrawCmd ( )
+{
+	if (m_point)
+		delete m_point;
+	for (PointList::iterator iter_cpoint = controlpoints.begin();
+			iter_cpoint != controlpoints.end(); iter_cpoint++)
+		delete (*iter_cpoint);
+} 
+
+
+
+// ----------------------------------------------------------------------------
+// ASSDrawEngine
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(ASSDrawEngine, GUI::AGGWindow)
+    EVT_PAINT  (ASSDrawEngine::OnPaint)
+END_EVENT_TABLE()
+
+// constructor
+ASSDrawEngine::ASSDrawEngine( wxWindow *parent, int extraflags )
+ : GUI::AGGWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
+        wxNO_FULL_REPAINT_ON_RESIZE | extraflags )
+{
+	pointsys = new PointSystem(1, 0, 0) ;
+	refresh_called = false;
+	fitviewpoint_hmargin = 10;
+	fitviewpoint_vmargin = 10;
+	setfitviewpoint = false;
+	rgba_shape = agg::rgba(0,0,1);
+	color_bg = PixelFormat::AGGType::color_type(255, 255, 255);
+	drawcmdset = wxT("m n l b s p c _"); //the spaces and underscore are in there for a reason, guess?
+	ResetEngine();
+}
+
+ASSDrawEngine::~ASSDrawEngine()
+{
+    ResetEngine ( false );
+    delete pointsys;
+}
+
+// parse ASS draw commands; returns the number of parsed commands
+int ASSDrawEngine::ParseASS ( wxString str )
+{
+	ResetEngine( false );
+	str.Replace(_T("\t"), _T(""));
+	str.Replace(_T("\r"), _T(""));
+	str.Replace(_T("\n"), _T(""));
+	str = str.Lower() + wxT(" _ _");
+	// we don't use regex because the pattern is too simple
+	wxStringTokenizer tkz( str, wxT(" ") );
+	wxString currcmd(wxT(""));
+	std::vector<int> val;
+	wxString token;
+	long tmp_int;
+	
+	bool n_collected = false;
+	DrawCmd_S *s_command = NULL;
+	wxPoint tmp_n_pnt;
+	
+	while ( tkz.HasMoreTokens() )
+	{
+		token = tkz.GetNextToken();
+		
+		if ( drawcmdset.Find(token) > -1 )
+		{
+			bool done;
+			
+			do {
+				done = true;
+				
+				// N
+				if (currcmd.IsSameAs(wxT("n")) && val.size() >= 2)
+				{
+					tmp_n_pnt.x = val[0], tmp_n_pnt.y = val[1];
+					n_collected = true;
+				}
+				else if(n_collected)
+				{
+					AppendCmd ( L, tmp_n_pnt.x, tmp_n_pnt.y );
+					n_collected = false;
+				}
+				
+				if (s_command != NULL)
+				{
+					bool ends = true;
+					if (currcmd.IsSameAs(wxT("p"))&& val.size() >= 2)
+					{
+						s_command->m_point->type = CP;
+						s_command->m_point->num = s_command->controlpoints.size() + 1;
+						s_command->controlpoints.push_back(s_command->m_point);
+						s_command->m_point = new Point(val[0], val[1], pointsys, MP, s_command);
+						ends = false;
+					}
+					else if (currcmd.IsSameAs(wxT("c")))
+						s_command->closed = true;
+
+					if (ends)
+					{
+						AppendCmd(s_command);
+						s_command = NULL;	
+					}
+				}
+				
+				// M
+				if (currcmd.IsSameAs(wxT("m")) && val.size() >= 2)
+					AppendCmd ( M, val[0], val[1] );
+				
+				// L
+				if (currcmd.IsSameAs(wxT("l")) && val.size() >= 2)
+				{
+					AppendCmd ( L, val[0], val[1] );
+					val.erase(val.begin(), val.begin()+2);
+					// L is greedy
+					if (val.size() >= 2)
+						done = false;
+				}
+				
+				// B
+				if (currcmd.IsSameAs(wxT("b")) && val.size() >= 6)
+				{
+					AppendCmd ( new DrawCmd_B(val[4], val[5], val[0], val[1],
+					val[2], val[3], pointsys, LastCmd()) );
+					val.erase(val.begin(), val.begin()+6);
+					// so is B
+					if (val.size() >= 6)
+						done = false;
+				}
+				
+				// S
+				if (currcmd.IsSameAs(wxT("s")) && val.size() >= 6)
+				{
+					int num = (val.size() / 2) * 2;
+					std::vector<int> val2;
+					int i = 0;
+					for (; i < num - 2; i++)
+						val2.push_back(val[i]);
+
+					s_command = new DrawCmd_S(val[num - 2], val[num - 1], val2, pointsys, LastCmd());
+				}
+				// more to come later
+			} while (!done);
+			
+			val.clear();
+			currcmd = token;
+		}
+		else if (token.ToLong( &tmp_int ))
+		{
+			val.push_back( (int) tmp_int );
+		}	
+	}
+	
+	return (int) cmds.size();
+}
+
+// generate ASS draw commands
+wxString ASSDrawEngine::GenerateASS ( )
+{
+    wxString output = _T("");
+    for (DrawCmdList::iterator iterate = cmds.begin(); iterate != cmds.end(); iterate++)
+         output = output + (*iterate)->ToString() + _T(" ");
+     return output;
+}
+
+// reset; delete all points and add a new M(0,0)
+void ASSDrawEngine::ResetEngine()
+{
+     ResetEngine(true);
+}
+
+// reset; delete all points and add a new M(0,0) if addM == true
+void ASSDrawEngine::ResetEngine( bool addM )
+{
+	for (DrawCmdList::iterator iterate = cmds.begin(); iterate != cmds.end(); iterate++)
+		delete (*iterate);
+	cmds.clear();
+	if (addM) AppendCmd( M, 0, 0 );
+}
+
+// Create draw command of type 'type' and m_point (x, y), append to the
+// list and return it
+DrawCmd* ASSDrawEngine::AppendCmd ( CMDTYPE type, int x, int y )
+{
+
+	// use a variation of this method
+	return AppendCmd( NewCmd( type, x, y ) );
+}
+
+// Append draw command
+DrawCmd* ASSDrawEngine::AppendCmd ( DrawCmd* cmd )
+{
+	// no NULL command!
+	if (cmd == NULL) return NULL;
+
+	// set dependency of this command on the m_point of the last command
+	if (!cmds.empty())
+		ConnectSubsequentCmds( cmds.back(), cmd );
+	else
+	{
+		// since this is the first command, if it's not an M make it into one
+		if (cmd->type != M)
+			cmd = NewCmd( M, cmd->m_point->x(), cmd->m_point->y() );
+		ConnectSubsequentCmds( NULL, cmd );
+	}
+	// put it in the list
+	cmds.push_back( cmd );
+
+	return cmd;
+}
+
+// create draw command of type 'type' and m_point (x, y), insert to the
+// list after the _cmd and return it
+DrawCmd* ASSDrawEngine::InsertCmd ( CMDTYPE type, int x, int y, DrawCmd* _cmd )
+{
+     // prepare the new DrawCmd
+     DrawCmd* c = NewCmd( type, x, y );
+
+     // use a variation of this method
+     InsertCmd( c, _cmd );
+
+     return NULL;
+}
+
+// insert draw command cmd after _cmd
+void ASSDrawEngine::InsertCmd ( DrawCmd* cmd, DrawCmd* _cmd )
+{
+     DrawCmdList::iterator iterate = cmds.begin();
+     for (; iterate != cmds.end() && *iterate != _cmd; iterate++)
+     {
+         // do nothing
+     }
+
+     if (iterate == cmds.end())
+     {
+        AppendCmd( cmd );
+     }
+     else
+     {
+        iterate++;
+        if (iterate != cmds.end())
+        {
+           ConnectSubsequentCmds( cmd, (*iterate) );
+        }
+        cmds.insert( iterate, cmd );
+        ConnectSubsequentCmds( _cmd, cmd );
+     }
+}
+
+DrawCmd* ASSDrawEngine::NewCmd ( CMDTYPE type, int x, int y )
+{
+     DrawCmd* c = NULL;
+
+     switch (type)
+     {
+        case M:
+             c = new DrawCmd_M(x, y, pointsys, LastCmd());
+             break;
+        case L:
+             c = new DrawCmd_L(x, y, pointsys, LastCmd());
+             break;
+        case B:
+             c = new DrawCmd_B(x, y, pointsys, LastCmd());
+             break;
+        case S:
+             c = new DrawCmd_S(x, y, pointsys, LastCmd());
+             break;
+     }
+     return c;
+}
+
+// returns the iterator for the list
+DrawCmdList::iterator ASSDrawEngine::Iterator ( )
+{
+	return cmds.begin();
+}
+
+// returns the 'end' iterator for the list
+DrawCmdList::iterator ASSDrawEngine::IteratorEnd ( )
+{
+	return cmds.end();
+}
+
+// returns the last command in the list
+DrawCmd* ASSDrawEngine::LastCmd ()
+{
+	if (cmds.size() == 0)
+		return NULL;
+	else
+		return cmds.back();
+}
+
+// move all points by relative amount of x, y coordinates
+void ASSDrawEngine::MovePoints ( int x, int y )
+{
+     DrawCmdList::iterator iterate = cmds.begin();
+     PointList::iterator iterate2;
+
+     for (; iterate != cmds.end(); iterate++)
+     {
+         (*iterate)->m_point->setXY( (*iterate)->m_point->x() + x, (*iterate)->m_point->y() + y );
+         for (iterate2 = (*iterate)->controlpoints.begin(); 
+		 	iterate2 != (*iterate)->controlpoints.end(); iterate2++)
+         {
+			(*iterate2)->setXY( (*iterate2)->x() + x, (*iterate2)->y() + y );
+         }
+	}
+}
+
+// transform all points using the calculation:
+//   | (m11)  (m12) | x | (x - mx) | + | nx |
+//   | (m21)  (m22) |   | (y - my) |   | ny |
+void ASSDrawEngine::Transform( float m11, float m12, float m21, float m22,
+							float mx, float my, float nx, float ny )
+{
+    DrawCmdList::iterator iterate = cmds.begin();
+    PointList::iterator iterate2;
+	float x, y;
+	for (; iterate != cmds.end(); iterate++)
+	{
+		x = ((float) (*iterate)->m_point->x()) - mx;
+		y = ((float) (*iterate)->m_point->y()) - my;
+		(*iterate)->m_point->setXY((int) (x * m11 + y * m12 + nx), (int) (x * m21 + y * m22 + ny) );
+		for (iterate2 = (*iterate)->controlpoints.begin();
+			 iterate2 != (*iterate)->controlpoints.end(); iterate2++)
+		{
+			x = ((float) (*iterate2)->x()) - mx;
+			y = ((float) (*iterate2)->y()) - my;
+			(*iterate2)->setXY((int) (x * m11 + y * m12 + nx), (int) (x * m21 + y * m22 + ny) );
+		}
+	}
+}
+
+// returns some DrawCmd if its m_point = (x, y)
+DrawCmd* ASSDrawEngine::PointAt ( int x, int y )
+{
+     DrawCmd* c = NULL;
+	 DrawCmdList::iterator iterate = cmds.begin();
+
+     for (; iterate != cmds.end(); iterate++)
+     {
+         if ( (*iterate)->m_point->IsAt( x, y ) )
+            c = (*iterate);
+     }
+
+     //delete &iterate;
+
+     return c;
+}
+
+// returns some DrawCmd if one of its control point = (x, y)
+// also set &point to refer to that control point
+DrawCmd* ASSDrawEngine::ControlAt ( int x, int y, Point* &point )
+{
+	DrawCmd* c = NULL;
+	point = NULL;
+	DrawCmdList::iterator cmd_iterator = cmds.begin();
+	PointList::iterator pnt_iterator;
+	PointList::iterator end;
+
+	for (; cmd_iterator != cmds.end(); cmd_iterator++)
+	{
+		pnt_iterator = (*cmd_iterator)->controlpoints.begin();
+		end = (*cmd_iterator)->controlpoints.end();
+		for (; pnt_iterator != end; pnt_iterator++)
+		{
+			if ( (*pnt_iterator)->IsAt( x, y ) )
+			{
+				c = (*cmd_iterator);
+				point = (*pnt_iterator);
+			}
+		}
+	}
+
+	return c;
+}
+
+// attempts to delete a commmand, returns true|false if successful|fail
+bool ASSDrawEngine::DeleteCommand ( DrawCmd* cmd )
+{
+	
+	DrawCmdList::iterator iterate = cmds.begin();
+	// can't delete the first command without deleting other commands first
+	if ( cmd == (*iterate) && cmds.size() > 1) return false;
+	
+	DrawCmd* lastiter = NULL;
+	
+	for (; iterate != cmds.end(); iterate++)
+	{
+		if ( cmd == (*iterate) )
+		{
+			iterate++;
+			DrawCmd* nxt = (iterate != cmds.end()? (*iterate):NULL);
+			ConnectSubsequentCmds( lastiter, nxt );
+			iterate--;
+			cmds.erase( iterate );
+			delete cmd;
+			break;
+		}
+		else
+			lastiter = (*iterate);
+	}
+	
+	return true;
+}
+
+// set stuff to connect two drawing commands cmd1 and cmd2 such that
+// cmd1 comes right before cmd2
+void ASSDrawEngine::ConnectSubsequentCmds (DrawCmd* cmd1, DrawCmd* cmd2)
+{
+	if (cmd1 != NULL)
+	{
+		cmd1->m_point->cmd_next = cmd2;
+	}
+	
+	if (cmd2 != NULL)
+	{
+		cmd2->prev = cmd1;
+	}
+}
+
+void ASSDrawEngine::RefreshDisplay() 
+{
+	if (!refresh_called)
+	{
+		Refresh();
+		refresh_called = true;
+	}
+}
+
+void ASSDrawEngine::OnPaint(wxPaintEvent& event)
+{
+	draw();
+	onPaint(event);
+	if (setfitviewpoint)
+	{
+		FitToViewPoint( fitviewpoint_hmargin, fitviewpoint_vmargin );
+		setfitviewpoint = false;
+		RefreshDisplay();
+	}
+}
+
+void ASSDrawEngine::draw()
+{
+	refresh_called = false;
+	
+	PixelFormat::AGGType pixf(rBuf);
+	RendererBase rbase(pixf);
+	RendererPrimitives rprim(rbase);
+	RendererSolid rsolid(rbase);
+
+	agg::trans_affine mtx;
+	ConstructPathsAndCurves(mtx, rm_path, rb_path, rm_curve);
+
+	rasterizer.reset();
+	update_rendered_bound_coords(true);
+	DoDraw(rbase, rprim, rsolid, mtx);
+	
+	delete rm_path, rb_path, rm_curve;
+}
+
+void ASSDrawEngine::ConstructPathsAndCurves(agg::trans_affine& mtx, 
+	trans_path*& _rm_path, trans_path*& _rb_path, agg::conv_curve<trans_path>*& _rm_curve)
+{
+    mtx *= agg::trans_affine_scaling(pointsys->scale);
+    mtx *= agg::trans_affine_translation(pointsys->originx, pointsys->originy);
+
+	m_path.remove_all();
+	b_path.remove_all();
+
+	DrawCmdList::iterator ci = cmds.begin();
+	while (ci != cmds.end())
+	{
+		AddDrawCmdToAGGPathStorage(*ci, m_path);
+		AddDrawCmdToAGGPathStorage(*ci, b_path, CTRL_LN);
+		ci++;
+	}
+	_rm_path = new trans_path(m_path, mtx);
+	_rb_path = new trans_path(b_path, mtx);
+    _rm_curve = new agg::conv_curve<trans_path>(*rm_path);
+}
+
+void ASSDrawEngine::DoDraw( RendererBase& rbase, RendererPrimitives& rprim, RendererSolid& rsolid, agg::trans_affine& mtx )
+{
+	Draw_Clear( rbase );
+	Draw_Draw( rbase, rprim, rsolid, mtx, rgba_shape );
+}
+
+void ASSDrawEngine::Draw_Clear( RendererBase& rbase )
+{
+	rbase.clear(color_bg);
+}
+
+void ASSDrawEngine::Draw_Draw( RendererBase& rbase, RendererPrimitives& rprim, RendererSolid& rsolid, agg::trans_affine& mtx, agg::rgba color )
+{
+    agg::conv_contour< agg::conv_curve< agg::conv_transform< agg::path_storage > > > contour(*rm_curve);
+	rasterizer.add_path(contour);
+	render_scanlines_aa_solid(rbase, color);
+}
+
+void ASSDrawEngine::AddDrawCmdToAGGPathStorage(DrawCmd* cmd, agg::path_storage& path, DRAWCMDMODE mode)
+{
+	if (mode == HILITE && cmd->prev)
+		path.move_to(cmd->prev->m_point->x(), cmd->prev->m_point->y());
+
+	switch(cmd->type)
+	{
+	case M:
+		path.move_to(cmd->m_point->x(),cmd->m_point->y());
+		break;
+
+	case B:
+		if (cmd->initialized)
+		{
+			//path.move_to(cmd->prev->m_point->x(),cmd->prev->m_point->y());
+			PointList::iterator iterate = cmd->controlpoints.begin();
+			int x[2], y[2];
+			x[0] = (*iterate)->x();
+			y[0] = (*iterate)->y();
+			iterate++;
+			x[1] = (*iterate)->x();
+			y[1] = (*iterate)->y();
+			path.curve4(x[0], y[0], x[1], y[1], cmd->m_point->x(),cmd->m_point->y());
+    		break;
+		}
+
+	case L:
+		if (mode == CTRL_LN)
+			path.move_to(cmd->m_point->x(),cmd->m_point->y());
+		else
+			path.line_to(cmd->m_point->x(),cmd->m_point->y());
+		break;
+		
+	case S:
+		unsigned np = cmd->controlpoints.size();
+        agg::pod_array<double> m_polygon(np * 2);
+        unsigned _pn = 0;
+		PointList::iterator iterate = cmd->controlpoints.begin();
+		while (iterate != cmd->controlpoints.end())
+		{
+	        m_polygon[_pn] = (*iterate)->x(); _pn++;
+	        m_polygon[_pn] = (*iterate)->y(); _pn++;
+	        iterate++;
+		}
+        //m_polygon[_pn++] = cmd->m_point->x();
+        //m_polygon[_pn++] = cmd->m_point->y();
+		//path.move_to(cmd->prev->m_point->x(),cmd->prev->m_point->y());
+		if (mode == CTRL_LN)
+		{
+			_pn = 0;
+			while (_pn < np * 2)
+			{
+				path.line_to((int) m_polygon[_pn],(int) m_polygon[_pn + 1]);
+				_pn += 2;
+			}
+	        path.line_to(cmd->m_point->x(), cmd->m_point->y());
+		}	
+		else
+		{	
+			//path.line_to((int) m_polygon[0],(int) m_polygon[1]);
+	        aggpolygon poly(&m_polygon[0], np, false, false);
+	        agg::conv_bcspline<agg::simple_polygon_vertex_source>  bspline(poly);
+	        bspline.interpolation_step(0.01);
+	        agg::path_storage npath;
+	        npath.join_path(bspline);
+	        path.join_path(npath);
+	        if (mode == HILITE)
+	        	path.move_to((int) m_polygon[np * 2 - 2], (int) m_polygon[np * 2 - 1] );
+	        path.line_to(cmd->m_point->x(), cmd->m_point->y());
+		}
+		break;
+	}	
+
+}
+
+void ASSDrawEngine::render_scanlines_aa_solid(RendererBase& rbase, agg::rgba rgba, bool affectboundaries)
+{
+	agg::render_scanlines_aa_solid(rasterizer, scanline, rbase, rgba);
+	if (affectboundaries) update_rendered_bound_coords();
+}
+
+void ASSDrawEngine::render_scanlines(RendererSolid& rsolid, bool affectboundaries)
+{
+	agg::render_scanlines(rasterizer, scanline, rsolid);
+	if (affectboundaries) update_rendered_bound_coords();
+}
+
+void ASSDrawEngine::update_rendered_bound_coords(bool rendered_fresh)
+{
+    int min_x = rasterizer.min_x();
+    int min_y = rasterizer.min_y();
+    int max_x = rasterizer.max_x();
+    int max_y = rasterizer.max_y();
+	if (min_x < rendered_min_x || rendered_fresh) rendered_min_x = min_x;
+	if (min_y < rendered_min_y || rendered_fresh) rendered_min_y = min_y;
+	if (max_x > rendered_max_x || rendered_fresh) rendered_max_x = max_x;
+	if (max_y > rendered_max_y || rendered_fresh) rendered_max_y = max_y;
+}
+
+void ASSDrawEngine::FitToViewPoint(int hmargin, int vmargin)
+{
+	wxSize v = GetClientSize();
+	double wide = rendered_max_x - rendered_min_x;
+	double high = rendered_max_y - rendered_min_y;
+	double widthratio = (double) (v.x - hmargin * 2) / wide;
+	double heightratio = (double) (v.y - vmargin * 2) / high;
+	double ratio = (widthratio < heightratio? widthratio:heightratio);
+	pointsys->scale = pointsys->scale * ratio;
+	if (pointsys->scale < 0.01) pointsys->scale = 0.01;
+	double new_min_x = pointsys->originx + (rendered_min_x - pointsys->originx) * ratio;
+	double new_max_x = pointsys->originx + (rendered_max_x - pointsys->originx) * ratio;
+	pointsys->originx += (v.x - new_max_x + new_min_x) / 2 - new_min_x;
+	double new_min_y = pointsys->originy + (rendered_min_y - pointsys->originy) * ratio;
+	double new_max_y = pointsys->originy + (rendered_max_y - pointsys->originy) * ratio;
+	pointsys->originy += (v.y - new_max_y + new_min_y) / 2 - new_min_y;
+	RefreshDisplay();
+}
+
+void ASSDrawEngine::SetFitToViewPointOnNextPaint(int hmargin, int vmargin)
+{
+	if (vmargin >= 0) fitviewpoint_vmargin = vmargin;
+	if (hmargin >= 0) fitviewpoint_hmargin = hmargin;
+	setfitviewpoint = true;
+}
+
+std::vector< bool > ASSDrawEngine::PrepareC1ContData()
+{
+	std::vector< bool > out;
+	for (DrawCmdList::iterator it = cmds.begin(); it != cmds.end(); it++)
+	{
+		bool c1 = false;
+		if ((*it)->type == B)
+		{
+			DrawCmd_B *cmdb = static_cast<DrawCmd_B *>(*it);
+			c1 = cmdb->C1Cont;
+		}
+		out.push_back(c1);
+	}
+	return out;
+}
diff --git a/assdraw/src/engine.hpp b/assdraw/src/engine.hpp
new file mode 100644
index 000000000..b730ec6fc
--- /dev/null
+++ b/assdraw/src/engine.hpp
@@ -0,0 +1,406 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        engine.hpp
+// Purpose:     header file for ASSDraw drawing engine
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include "_common.hpp"
+
+// we use these 2 standard libraries
+#include <math.h>
+#include <list>
+#include <set>
+#include <vector>
+
+// agg support
+#include "wxAGG/AGGWindow.h"
+#include "agg_color_rgba.h"
+#include "agg_rasterizer_scanline_aa.h"
+#include "agg_scanline_p.h"
+#include "agg_renderer_base.h"
+#include "agg_renderer_primitives.h"
+#include "agg_renderer_scanline.h"
+#include "agg_path_storage.h"
+#include "agg_curves.h"
+#include "agg_conv_curve.h"
+#include "agg_conv_contour.h"
+#include "agg_conv_stroke.h"
+#include "agg_conv_bcspline.h"
+#include "agg_math.h"
+
+#define DEFAULT_SCALE 10
+
+// this header file declare the following classes
+class DrawEngine;
+class Point;
+class PointSystem;
+class DrawCmd;
+
+typedef std::list<DrawCmd*> DrawCmdList;
+typedef std::list<Point*> PointList;
+typedef std::set<Point*> PointSet;
+
+// Command type
+enum CMDTYPE 
+{
+     M = 0,
+     N = 1,
+     L = 2,
+     B = 3,
+     S = 4,
+     P = 5,
+     C = 6     
+};
+
+// Point type
+enum POINTTYPE
+{
+	MP, // main point
+	CP  // control point
+};
+
+// A PointSystem is a centralized entity holding the parameters:
+// scale, originx and originy, all of which are needed by Point
+class PointSystem
+{
+public:
+	double scale, originx, originy;
+
+	PointSystem ( double sc = 1.0, double origx = 0.0, double origy = 0.0 )
+	{ 	Set( sc, origx, origy ); }
+
+	// set scale, originx and originy;
+	void Set( double sc, double origx, double origy )
+	{ scale = sc, originx = origx, originy = origy; }
+	
+	wxRealPoint ToWxRealPoint ( double x, double y )
+	{ return wxRealPoint( originx + x * scale, originy + y * scale ); }
+
+	// given drawing command coordinates returns the wxPoint on the GUI
+	wxPoint ToWxPoint ( double x, double y )
+	{ return wxPoint( (int) (originx + x * scale), (int) (originy + y * scale) ); }
+
+	// given wxPoint on the GUI returns the nearest drawing command coords
+	void FromWxPoint ( int wxpx, int wxpy, int &x, int &y )
+	{
+		x = int( floor( ((double) wxpx - originx) / scale + 0.5 ) );
+		y = int( floor( ((double) wxpy - originy) / scale + 0.5 ) );
+	}                   
+
+	// given wxPoint on the GUI returns the nearest drawing command coords
+	void FromWxPoint ( wxPoint wxp, int &x, int &y )
+	{
+		FromWxPoint( wxp.x, wxp.y, x, y );
+	}
+};
+
+// The point class
+// note: this actually refers to the x,y-coordinate in drawing commands,
+// not the coordinate in the GUI
+class Point
+{
+public:
+	POINTTYPE type;
+	PointSystem *pointsys;
+
+	// drawing commands that depend on this point
+	DrawCmd* cmd_main;
+	DrawCmd* cmd_next;
+	bool isselected;
+	unsigned num;
+
+	// constructor
+	//Point ( ) { cmd_main = NULL; cmd_next = NULL; }
+
+	// constructor
+	Point ( int _x, int _y, PointSystem* ps, POINTTYPE t, DrawCmd* cmd, unsigned n = 0 );
+
+	// getters
+	int x() { return x_; }
+
+	int y() { return y_; }
+
+	//set x and y
+	void setXY( int _x, int _y);
+	
+	// simply returns true if px and py are the coordinate values
+	bool IsAt( int px, int py );
+
+	// convert this point to wxPoint using scale and originx, originy
+	wxPoint ToWxPoint () { return ToWxPoint(true); }
+
+	// convert this point to wxPoint using scale;
+	// also use originx and originy if useorigin = true
+	wxPoint ToWxPoint (bool useorigin);
+
+	// check if wxpoint is nearby this point
+	bool CheckWxPoint ( wxPoint wxpoint );
+
+private:
+	int x_, y_;
+
+};
+
+// The base class for all draw commands
+class DrawCmd
+{
+public:
+	CMDTYPE type;
+	      
+	// main point (almost every command has one)
+	// for B and S it's the last (destination) point
+	Point* m_point;
+
+	// other points than the main point
+	// subclasses must populate this list even if they define 
+	// new variables for other points
+	PointList controlpoints; 
+
+	// Linked list feature
+	DrawCmd *prev;
+
+	// Must set to true if the next command should NOT utilize this command
+	// for the drawing
+	bool dobreak;
+
+	// Set to true if invisible m_point (not drawn)
+	bool invisible;
+
+	// true if this DrawCmd has been initialized with Init(), false otherwise
+	// (initialized means that the control points have been generated)
+	bool initialized;
+
+	// -----------------------------------------------------------
+	// Constructor(s)
+	DrawCmd ( int x, int y, PointSystem *ps, DrawCmd *pv );
+	      
+	// Destructor
+	virtual ~DrawCmd ();
+
+	// Init the draw command (for example to generate the control points)
+	virtual void Init(unsigned n = 0) { initialized = true; }
+
+	virtual wxString ToString() { return wxT(""); }
+
+};
+
+class ASSDrawEngine: public GUI::AGGWindow
+{
+public:
+	ASSDrawEngine( wxWindow *parent, int extraflags = 0 );
+
+    // destructor
+    ~ASSDrawEngine();
+
+	virtual void SetDrawCmdSet(wxString set) { drawcmdset = set; }
+
+    virtual void ResetEngine();
+    virtual void ResetEngine(bool addM);
+    virtual void RefreshDisplay();
+
+	void FitToViewPoint(int hmargin, int vmargin);
+	void SetFitToViewPointOnNextPaint(int hmargin = -1, int vmargin = -1);
+
+	PointSystem* _PointSystem() { return pointsys; }
+
+	// ASS draw commands; returns the number of parsed commands
+	virtual int ParseASS ( wxString str );
+	// generate ASS draw commands
+	virtual wxString GenerateASS ( );
+
+	// drawing
+    virtual void OnPaint(wxPaintEvent &event);
+
+	// -------------------- adding new commands ----------------------------
+
+	// create draw command of type 'type' and m_point (x, y), append to the
+	// list and return it
+	virtual DrawCmd* AppendCmd ( CMDTYPE type, int x, int y );
+
+	// append draw command
+	virtual DrawCmd* AppendCmd ( DrawCmd* cmd );
+
+	// create draw command of type 'type' and m_point (x, y), insert to the
+	// list after the _cmd and return it
+	virtual DrawCmd* InsertCmd ( CMDTYPE type, int x, int y, DrawCmd* _cmd );
+
+	// insert draw command cmd after _cmd
+	virtual void InsertCmd ( DrawCmd* cmd, DrawCmd* _cmd );
+
+	// Create new DrawCmd
+	DrawCmd* NewCmd ( CMDTYPE type, int x, int y );
+
+	// -------------------- read/modify commands ---------------------------
+
+	// returns the iterator for the list
+	virtual DrawCmdList::iterator Iterator ( );
+
+	// returns the 'end' iterator for the list
+	virtual DrawCmdList::iterator IteratorEnd ( );
+
+	// returns the last command in the list
+	virtual DrawCmd* LastCmd ();
+
+	// returns the total number of commands in the list
+	//virtual int CmdCount () { return cmds.size(); }
+
+	// move all points by relative amount of x, y coordinates
+	virtual void MovePoints ( int x, int y );
+
+	// transform all points using the calculation:
+	//   | (m11)  (m12) | x | (x - mx) | + | nx |
+	//   | (m21)  (m22) |   | (y - my) |   | ny |
+	virtual void Transform( float m11, float m12, float m21, float m22,
+							float mx, float my, float nx, float ny );
+
+	// returns some DrawCmd if its m_point = (x, y)
+	virtual DrawCmd* PointAt ( int x, int y );
+
+	// returns some DrawCmd if one of its control point = (x, y)
+	// also set &point to refer to that control point
+	virtual DrawCmd* ControlAt ( int x, int y, Point* &point );
+
+	// attempts to delete a commmand, returns true|false if successful|fail
+	virtual bool DeleteCommand ( DrawCmd* cmd );
+	
+	agg::rgba rgba_shape;
+	PixelFormat::AGGType::color_type color_bg;
+
+protected:
+	/// The AGG base renderer
+	typedef agg::renderer_base<PixelFormat::AGGType> RendererBase;
+	/// The AGG primitives renderer
+	typedef agg::renderer_primitives<RendererBase> RendererPrimitives;
+	/// The AGG solid renderer
+	typedef agg::renderer_scanline_aa_solid<RendererBase> RendererSolid;
+	
+	enum DRAWCMDMODE {
+		NORMAL,
+		CTRL_LN,
+		HILITE
+	};
+
+	DrawCmdList cmds;
+	wxString drawcmdset;
+
+	PointSystem* pointsys;
+	
+	// for FitToViewPoint feature
+	bool setfitviewpoint;
+	int fitviewpoint_vmargin, fitviewpoint_hmargin;
+
+	// AGG
+	agg::rasterizer_scanline_aa<> rasterizer;   ///< Scanline rasterizer
+	agg::scanline_p8  scanline;                 ///< Scanline container
+	void render_scanlines_aa_solid(RendererBase& rbase, agg::rgba rbga, bool affectboundaries = true);
+	void render_scanlines(RendererSolid& rsolid, bool affectboundaries = true);
+	int rendered_min_x, rendered_min_y, rendered_max_x, rendered_max_y; //bounding coord of rendered shapes
+	void update_rendered_bound_coords(bool rendered_fresh = false);
+
+	typedef agg::conv_transform<agg::path_storage> trans_path;
+	agg::path_storage m_path, b_path;
+	trans_path *rm_path, *rb_path;
+	agg::conv_curve<trans_path> *rm_curve;
+
+	void draw();
+	virtual void ConstructPathsAndCurves(agg::trans_affine& mtx, trans_path*& _rm_path, trans_path*& _rb_path, agg::conv_curve<trans_path>*& _rm_curve);
+	virtual void DoDraw( RendererBase& rbase, RendererPrimitives& rprim, RendererSolid& rsolid, agg::trans_affine& mtx  );
+	virtual void Draw_Clear( RendererBase& rbase );
+	virtual void Draw_Draw( RendererBase& rbase, RendererPrimitives& rprim, RendererSolid& rsolid, agg::trans_affine& mtx, agg::rgba color );
+	bool refresh_called;
+	
+	// set stuff to connect two drawing commands cmd1 and cmd2 such that
+	// cmd1 comes right before cmd2
+	virtual void ConnectSubsequentCmds (DrawCmd* cmd1, DrawCmd* cmd2);
+	
+	virtual void AddDrawCmdToAGGPathStorage(DrawCmd* cmd, agg::path_storage& path, DRAWCMDMODE mode = NORMAL);
+	
+	virtual std::vector< bool > PrepareC1ContData();
+
+	DECLARE_EVENT_TABLE()
+};
+
+namespace agg
+{
+    class simple_polygon_vertex_source
+    {
+    public:
+        simple_polygon_vertex_source(const double* polygon, unsigned np, 
+                                     bool roundoff = false,
+                                     bool close = true) :
+            m_polygon(polygon),
+            m_num_points(np),
+            m_vertex(0),
+            m_roundoff(roundoff),
+            m_close(close)
+        {
+        }
+
+        void close(bool f) { m_close = f;    }
+        bool close() const { return m_close; }
+
+        void rewind(unsigned)
+        {
+            m_vertex = 0;
+        }
+
+        unsigned vertex(double* x, double* y)
+        {
+            if(m_vertex > m_num_points) return path_cmd_stop;
+            if(m_vertex == m_num_points) 
+            {
+                ++m_vertex;
+                return path_cmd_end_poly | (m_close ? path_flags_close : 0);
+            }
+            *x = m_polygon[m_vertex * 2];
+            *y = m_polygon[m_vertex * 2 + 1];
+            if(m_roundoff)
+            {
+                *x = floor(*x) + 0.5;
+                *y = floor(*y) + 0.5;
+            }
+            ++m_vertex;
+            return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to;
+        }
+
+    private:
+        const double* m_polygon;
+        unsigned m_num_points;
+        unsigned m_vertex;
+        bool     m_roundoff;
+        bool     m_close;
+    };
+};
+
+typedef agg::simple_polygon_vertex_source aggpolygon;
diff --git a/assdraw/src/enums.hpp b/assdraw/src/enums.hpp
new file mode 100644
index 000000000..e59217056
--- /dev/null
+++ b/assdraw/src/enums.hpp
@@ -0,0 +1,113 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#pragma once
+
+// enum for IDs of menus
+enum {
+	MENU_DUMMY = 200,
+	MENU_CLEAR,
+	MENU_PREVIEW,
+	MENU_TRANSFORM,
+	MENU_LIBRARY,
+	MENU_HELP,
+	MENU_RESETPERSPECTIVE,
+	MENU_SETTINGS,
+	MENU_UNDO,
+	MENU_REDO,
+	MENU_PASTE,
+	MENU_BGIMG_LOAD,
+	MENU_BGIMG_ALPHA,
+	MENU_BGIMG_REMOVE,
+	MENU_RECENTER,
+	MENU_TBAR,
+	MENU_REPOS_TOPLEFT,
+	MENU_REPOS_TOPRIGHT,
+	MENU_REPOS_CENTER,
+	MENU_REPOS_BOTLEFT,
+	MENU_REPOS_BOTRIGHT,
+	MENU_BGIMG_RECENTER,
+	MENU_REPOS_BGTOPLEFT,
+	MENU_REPOS_BGTOPRIGHT,
+	MENU_REPOS_BGCENTER,
+	MENU_REPOS_BGBOTLEFT,
+	MENU_REPOS_BGBOTRIGHT,
+	MENU_DRC_LNTOBEZ,
+	MENU_DRC_C1CONTBEZ,
+	MENU_DRC_BEZTOLN,
+	MENU_DRC_MOVE00,
+	MENU_TB_ALL,
+	MENU_TB_NONE,
+	MENU_TB_DOCK,
+	MENU_TB_UNDOCK,
+	MENU_TB_DRAW,
+	MENU_TB_MODE,
+	MENU_TB_BGIMG
+};
+
+// enum for modes (i.e. create m, b, l etc or normal mode)
+// also use as tools IDs
+enum MODE
+{
+    MODE_ARR = 100,
+    MODE_M = 101,
+    MODE_N = 102,
+    MODE_L = 103,
+    MODE_B = 104,
+    MODE_S = 105,
+    MODE_P = 106,
+    MODE_C = 107,
+    MODE_DEL = 108,
+	MODE_SCALEROTATE = 109,
+	MODE_NUT_BILINEAR = 110
+};
+
+// enum for IDs of other tools on the toolbar
+enum {
+     TB_CLEAR = 111,
+     TB_EDITSRC = 112,
+     TB_PREVIEW = 113,
+     TB_TRANSFORM = 114,
+     TB_HELP = 115,
+     TB_ZOOMSLIDER = 116,
+     TB_BGALPHA_SLIDER = 117
+};
+
+enum DRAGMODETOOL
+{
+    DRAG_DWG = 120,
+    DRAG_BGIMG = 121,
+    DRAG_BOTH = 122
+};
+
+struct DRAGMODE
+{
+	bool drawing;
+	bool bgimg;
+	DRAGMODE() { drawing = true, bgimg = false; }
+	DRAGMODE(bool d, bool b) { drawing = d, bgimg = b; }
+};
diff --git a/assdraw/src/include_once.hpp b/assdraw/src/include_once.hpp
new file mode 100644
index 000000000..aa7624ac7
--- /dev/null
+++ b/assdraw/src/include_once.hpp
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        include_once.hpp
+// Purpose:     A header file that is included exactly once for the whole code
+//              (supposed to be included by assdraw.cpp only)
+//              Put must-define-exactly-once codes here
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+// tooltips
+const wxString TIPS_CLEAR = wxT("Clear the canvas and create a new drawing");
+const wxString TIPS_EDITSRC = wxT("Edit the source");
+const wxString TIPS_PREVIEW = wxT("Draw the shapes without enlarged points and control points");
+const wxString TIPS_TRANSFORM = wxT("Transform the drawing using matrix transformation");
+const wxString TIPS_LIBRARY = wxT("Shapes library");
+const wxString TIPS_HELP = wxT("Help! Help!");
+const wxString TIPS_PASTE = wxT("Depending on what's in the clipboard, import as drawing commands or background");
+const wxString TIPS_UNDO = wxT("Undo last action");
+const wxString TIPS_REDO = wxT("Redo last undo");
+const wxString TIPS_ARR = wxT("Drag mode");
+const wxString TIPS_M = wxT("Draw M mode (Close current shape and move the virtual pen to a new point)");
+const wxString TIPS_N = wxT("Draw N mode (Same as M but doesn't close the shape)");
+const wxString TIPS_L = wxT("Draw L mode (Straight line)");
+const wxString TIPS_B = wxT("Draw B mode (Cubic Bezier curve)");
+const wxString TIPS_S = wxT("Draw S mode (Spline)");
+const wxString TIPS_P = wxT("Draw P mode (Extends a spline with another point)");
+const wxString TIPS_C = wxT("Draw C mode (Close the last spline)");
+const wxString TIPS_DEL = wxT("Delete mode");
+const wxString TIPS_NUTB = wxT("Bilinear transformation mode: Drag the vertices to distort the shape; Dragging an edge moves two adjacent vertices together");
+const wxString TIPS_SCALEROTATE = wxT("Scale/Rotate mode: Drag a vertex or an edge to rescale the shape; Right-drag to rotate");
+const wxString TIPS_DWG = wxT("Right-dragging pans drawing, mousewheel zooms in/out drawing");
+const wxString TIPS_BGIMG = wxT("Right-dragging pans background, mousewheel zooms in/out background");
+const wxString TIPS_BOTH = wxT("Right-dragging pans drawing & background, mousewheel zooms in/out drawing & background");
+
+const wxString TBNAME_DRAW = wxT("Canvas");
+const wxString TBNAME_MODE = wxT("Drawing mode");
+const wxString TBNAME_BGIMG = wxT("Background");
+const wxString TBNAME_ZOOM = wxT("Zoom");
+
+wxString ASSDrawTransformDlg::combo_templatesStrings[] = {
+	_("<Select>"),
+	_("Move 5 units down"),
+	_("Move 5 units right"),
+	_("Rotate 90� clockwise at (1, 2)"),
+	_("Rotate 90� counterclockwise at (-1, 2)"),
+	_("Rotate 180� at (0, 0)"),
+	_("Flip horizontally at X = 4"),
+	_("Flip vertically at Y = 3"),
+	_("Scale up horizontally by a factor of 2"),
+	_("Scale up vertically by a factor of 3")
+};
+
+int ASSDrawTransformDlg::combo_templatesCount = 10;
+
+EightDouble ASSDrawTransformDlg::combo_templatesValues[] = {
+	{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }, //<Select>
+	{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 5.0f }, //5 units down
+	{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 5.0f, 0.0f }, //5 units left
+	{ 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 2.0f, 1.0f, 2.0f }, //90 CW (1,2)
+	{ 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 2.0f, -1.0f, 2.0f }, //90 CCW, (-1,2)
+	{ -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f }, //180 (0,0)
+	{ -1.0f, 0.0f, 0.0f, 1.0f, 4.0f, 0.0f, 4.0f, 0.0f }, //Flip X = 4
+	{ 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 3.0f, 0.0f, 3.0f }, //Flip Y = 3
+	{ 2.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }, //Scale X * 2
+	{ 1.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f } //Scale Y * 3
+};
diff --git a/assdraw/src/library.cpp b/assdraw/src/library.cpp
new file mode 100644
index 000000000..1f6932eb0
--- /dev/null
+++ b/assdraw/src/library.cpp
@@ -0,0 +1,259 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "assdraw.hpp"
+#include "library.hpp"
+
+#include <wx/clipbrd.h>
+
+BEGIN_EVENT_TABLE(ASSDrawShapePreview, ASSDrawEngine)
+    EVT_SIZE(ASSDrawShapePreview::OnSize)
+END_EVENT_TABLE()
+
+ASSDrawShapePreview::ASSDrawShapePreview( wxWindow *parent, ASSDrawShapeLibrary *_shapelib, wxString initialcmds )
+	: ASSDrawEngine(parent, wxSIMPLE_BORDER)
+{
+	shapelib = _shapelib;
+	if (ParseASS(initialcmds) > 0)
+		SetFitToViewPointOnNextPaint(5, 5);
+	cb = new wxCheckBox(this, wxID_ANY, "");
+}
+
+void ASSDrawShapePreview::OnSize(wxSizeEvent& event)
+{
+	return;
+	wxSize siz = event.GetSize();
+	
+	if (shapelib->layout == HORIZONTAL)
+		SetSize(siz.x, siz.x);
+	else
+		SetSize(siz.y, siz.y);	
+	SetFitToViewPointOnNextPaint(10, 10);
+}
+
+BEGIN_EVENT_TABLE(ASSDrawShapeLibrary, wxScrolledWindow)
+    EVT_SIZE(ASSDrawShapeLibrary::OnSize)
+    EVT_MENU_RANGE(MENU_RANGE_START, MENU_RANGE_END, ASSDrawShapeLibrary::OnPopupMenuClicked)
+    EVT_TOOL(TOOL_SAVE, ASSDrawShapeLibrary::SaveShapeFromCanvas)
+    EVT_TOOL_RANGE(TOOL_CHECK, TOOL_UNCHECK, ASSDrawShapeLibrary::CheckUncheckAllPreviews)
+    EVT_TOOL(TOOL_DELETE, ASSDrawShapeLibrary::DeleteChecked)
+END_EVENT_TABLE()
+
+ASSDrawShapeLibrary::ASSDrawShapeLibrary( wxWindow *parent, ASSDrawFrame *frame ) 
+	: wxScrolledWindow(parent, wxID_ANY)
+{
+	m_frame = frame;
+	//sizer = NULL;
+	layout = VERTICAL;
+	
+	wxToolBar *tbar = new wxToolBar(this, wxID_ANY, __DPDS__ , wxTB_HORIZONTAL | wxNO_BORDER | wxTB_FLAT | wxTB_NODIVIDER);
+	tbar->SetMargins(0, 3);
+	tbar->AddTool(TOOL_SAVE, wxBITMAP(add), "Save canvas");
+	tbar->AddSeparator();
+	tbar->AddTool(TOOL_CHECK, wxBITMAP(check), "Select all");
+	tbar->AddTool(TOOL_UNCHECK, wxBITMAP(uncheck), "Select none");
+	tbar->AddTool(TOOL_DELETE, wxBITMAP(delcross), "Delete selected");
+
+	libarea = new wxScrolledWindow(this, wxID_ANY, __DPDS__ , wxScrolledWindowStyle | wxSIMPLE_BORDER);
+	libarea->SetBackgroundColour(wxColour(0xFF, 0xFF, 0x99));
+	sizer = new wxFlexGridSizer(0, 1, 0, 0);
+	((wxFlexGridSizer*) sizer)->AddGrowableCol(0);
+	libarea->SetSizer(sizer);
+	libarea->SetScrollbars(20, 20, 50, 50);
+	libsizer = new wxFlexGridSizer(2, 1, 0, 0);
+	libsizer->AddGrowableCol(0);
+	libsizer->AddGrowableRow(1);
+	libsizer->Add(tbar, 0, wxBOTTOM, 2);
+	libsizer->Add(libarea,1,wxEXPAND);
+	tbar->Realize();
+	libsizer->Layout();
+
+	SetSizer(libsizer);
+}
+
+void ASSDrawShapeLibrary::OnSize(wxSizeEvent& event)
+{
+	if (sizer == NULL || sizer->GetChildren().size() == 0) return;
+
+	wxSize siz = GetClientSize();
+	libsizer->SetDimension(0, 0, siz.x, siz.y);
+			
+	UpdatePreviewDisplays();
+}
+
+ASSDrawShapePreview* ASSDrawShapeLibrary::AddShapePreview(wxString cmds, bool addtotop)
+{
+	ASSDrawShapePreview *prev = new ASSDrawShapePreview(libarea, this, cmds);
+	prev->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(ASSDrawShapeLibrary::OnMouseLeftDClick), NULL, this);
+	prev->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(ASSDrawShapeLibrary::OnMouseRightClick), NULL, this);
+	ASSDrawFrame::wxColourToAggRGBA(m_frame->colors.library_shape, prev->rgba_shape);
+	if (addtotop)
+		sizer->Insert(0, prev, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5);
+	else
+		sizer->Add(prev, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5);
+	UpdatePreviewDisplays();
+	return prev;
+}
+
+void ASSDrawShapeLibrary::UpdatePreviewDisplays()
+{
+	wxSize siz = GetClientSize();
+	int dim = siz.x - 15;
+	libarea->Show(false);
+	wxwxSizerItemListNode *node = sizer->GetChildren().GetFirst();
+	while (node != NULL)
+	{
+		ASSDrawShapePreview *shprvw = (ASSDrawShapePreview *) node->GetData()->GetWindow();
+		shprvw->SetSize(dim, dim);
+		sizer->SetItemMinSize(shprvw, dim - 20, dim - 20);
+		shprvw->SetFitToViewPointOnNextPaint(10, 10);
+		shprvw->Refresh();
+		node = node->GetNext();
+	}
+	sizer->Layout();
+	sizer->FitInside(libarea);	
+	libarea->Show(true);
+}
+
+void ASSDrawShapeLibrary::OnMouseLeftDClick(wxMouseEvent &event)
+{
+	ASSDrawShapePreview *preview = (ASSDrawShapePreview *) event.GetEventObject();
+	LoadToCanvas(preview);
+}
+
+void ASSDrawShapeLibrary::OnMouseRightClick(wxMouseEvent &event)
+{
+	ASSDrawShapePreview *prev = (ASSDrawShapePreview *) event.GetEventObject();
+	if (prev && prev->shapelib == this)
+	{
+		activepreview = prev;
+		wxMenu *menu = new wxMenu;
+		wxMenuItem *menuload = new wxMenuItem(menu, MENU_LOAD, wxT("Load to canvas"));
+		wxFont f = menuload->GetFont();
+		f.SetWeight(wxFONTWEIGHT_BOLD);
+		menuload->SetFont(f);
+		menu->Append(menuload);
+		//menu->Append(MENU_LOAD, wxT("Load to canvas"))->GetFont().SetWeight(wxFONTWEIGHT_BOLD);
+		menu->Append(MENU_COPYCLIPBOARD, wxT("Copy commands to clipboard"));
+		menu->Append(MENU_SAVECANVAS, wxT("Save canvas here"));
+		wxMenu *submenu = new wxMenu;
+		submenu->Append(MENU_DELETE, wxT("Confirm delete?"));
+		menu->Append(MENU_DUMMY, wxT("Delete from library"), submenu);
+		PopupMenu(menu);
+		delete menu;
+	}
+}
+
+void ASSDrawShapeLibrary::OnPopupMenuClicked(wxCommandEvent &event)
+{
+	int id = event.GetId();
+	switch(id)
+	{
+	case MENU_LOAD:
+		LoadToCanvas(activepreview);
+		break;
+	case MENU_COPYCLIPBOARD:
+		if (wxTheClipboard->Open())
+		{
+			if (wxTheClipboard->IsSupported( wxDF_TEXT ))
+			{
+				wxTheClipboard->SetData( new wxTextDataObject( activepreview->GenerateASS() ) );
+			}
+			wxTheClipboard->Close();
+		}
+		break;
+	case MENU_SAVECANVAS:
+		activepreview->ParseASS(m_frame->m_canvas->GenerateASS());
+		activepreview->SetFitToViewPointOnNextPaint();
+		activepreview->RefreshDisplay();
+		break;
+	case MENU_DELETE:
+		sizer->Detach(activepreview);
+		activepreview->Show(false);
+		activepreview->Destroy();
+		UpdatePreviewDisplays();
+		Refresh();
+		break;
+	}
+}
+
+void ASSDrawShapeLibrary::SaveShapeFromCanvas(wxCommandEvent& WXUNUSED(event))
+{
+	AddShapePreview(m_frame->m_canvas->GenerateASS(), true);	
+}
+
+void ASSDrawShapeLibrary::CheckUncheckAllPreviews(wxCommandEvent &event)
+{
+	bool checked = event.GetId() == TOOL_CHECK;	
+	wxwxSizerItemListNode *node = sizer->GetChildren().GetFirst();
+	while (node != NULL)
+	{
+		ASSDrawShapePreview *shprvw = (ASSDrawShapePreview *) node->GetData()->GetWindow();
+		shprvw->cb->SetValue(checked);
+		node = node->GetNext();
+	}
+}
+
+void ASSDrawShapeLibrary::DeleteChecked(wxCommandEvent& WXUNUSED(event))
+{
+	wxwxSizerItemListNode *node = sizer->GetChildren().GetFirst();
+	while (node != NULL)
+	{
+		ASSDrawShapePreview *shprvw = (ASSDrawShapePreview *) node->GetData()->GetWindow();
+		if (shprvw->cb->GetValue())
+		{
+			sizer->Detach(shprvw);
+			shprvw->Show(false);
+			shprvw->Destroy();
+		}
+		node = node->GetNext();
+	}
+	UpdatePreviewDisplays();
+	Refresh();
+}
+
+std::vector< ASSDrawShapePreview *> ASSDrawShapeLibrary::GetShapePreviews()
+{
+	std::vector< ASSDrawShapePreview *> out;
+	wxwxSizerItemListNode *node = sizer->GetChildren().GetFirst();
+	while (node != NULL)
+	{
+		ASSDrawShapePreview *shprvw = (ASSDrawShapePreview *) node->GetData()->GetWindow();
+		out.push_back(shprvw);
+		node = node->GetNext();
+	}
+	return out;
+}
+
+void ASSDrawShapeLibrary::LoadToCanvas(ASSDrawShapePreview *preview)
+{
+	m_frame->m_canvas->AddUndo("Load shape from library");
+	m_frame->m_canvas->ParseASS(preview->GenerateASS());
+	m_frame->m_canvas->RefreshDisplay();
+	m_frame->m_canvas->RefreshUndocmds();
+	m_frame->UpdateFrameUI();
+}	
diff --git a/assdraw/src/library.hpp b/assdraw/src/library.hpp
new file mode 100644
index 000000000..20179d12f
--- /dev/null
+++ b/assdraw/src/library.hpp
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#pragma once
+
+#include "engine.hpp"
+#include <wx/scrolwin.h>
+
+class ASSDrawFrame;
+class ASSDrawShapeLibrary;
+
+enum LIBLAYOUT { VERTICAL, HORIZONTAL };
+
+enum {
+	MENU_RANGE_START = 450,
+	MENU_LOAD,
+	MENU_COPYCLIPBOARD,
+	MENU_SAVECANVAS,
+	MENU_DELETE,
+	MENU_RANGE_END,
+	TOOL_SAVE,
+	TOOL_CHECK,
+	TOOL_UNCHECK,
+	TOOL_DELETE
+};
+
+class ASSDrawShapePreview : public ASSDrawEngine
+{
+protected:
+	ASSDrawShapePreview( wxWindow *parent, ASSDrawShapeLibrary *shapelib, wxString initialcmds = _T(""));
+	virtual void OnSize(wxSizeEvent& event);
+
+	ASSDrawShapeLibrary *shapelib;
+	wxCheckBox *cb;
+	DECLARE_EVENT_TABLE()
+	friend class ASSDrawShapeLibrary;
+};
+
+class ASSDrawShapeLibrary : public wxScrolledWindow
+{
+public:
+	ASSDrawShapeLibrary( wxWindow *parent, ASSDrawFrame *frame );
+	virtual ASSDrawShapePreview* AddShapePreview(wxString cmds, bool addtotop = false);
+	virtual void OnSize(wxSizeEvent& event);
+	virtual void OnMouseLeftDClick(wxMouseEvent &event);
+	virtual void OnMouseRightClick(wxMouseEvent &event);
+	virtual void OnPopupMenuClicked(wxCommandEvent &event);
+	virtual void SaveShapeFromCanvas(wxCommandEvent& WXUNUSED(event));
+	virtual void CheckUncheckAllPreviews(wxCommandEvent &event);
+	virtual void DeleteChecked(wxCommandEvent& WXUNUSED(event));
+	virtual void UpdatePreviewDisplays();
+	virtual std::vector< ASSDrawShapePreview *> GetShapePreviews();
+	virtual void LoadToCanvas(ASSDrawShapePreview *preview);
+	
+	wxScrolledWindow* libarea;
+	wxFlexGridSizer *libsizer;
+	wxSizer* sizer;
+	LIBLAYOUT layout;
+protected:
+	ASSDrawFrame *m_frame;
+	ASSDrawShapePreview *activepreview;
+
+	DECLARE_EVENT_TABLE()
+};
diff --git a/assdraw/src/resource.h b/assdraw/src/resource.h
new file mode 100644
index 000000000..dab23b6f5
--- /dev/null
+++ b/assdraw/src/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by assdraw.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        105
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/assdraw/src/settings.cpp b/assdraw/src/settings.cpp
new file mode 100644
index 000000000..41bd680c1
--- /dev/null
+++ b/assdraw/src/settings.cpp
@@ -0,0 +1,223 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// Name:        settings.cpp
+// Purpose:     settings property grid
+// Author:      ai-chan
+// Created:     08/26/06
+// Copyright:   (c) ai-chan
+// Licence:     3-clause BSD
+///////////////////////////////////////////////////////////////////////////////
+
+#include "assdraw.hpp"
+#include "settings.hpp"
+
+DEFINE_EVENT_TYPE(wxEVT_SETTINGS_CHANGED)
+
+// ----------------------------------------------------------------------------
+// ASSDrawSettingsDialog
+// ----------------------------------------------------------------------------
+
+ASSDrawSettingsDialog::ASSDrawSettingsDialog(wxWindow *parent, ASSDrawFrame *frame, int id)
+ : wxPanel(parent, id)
+{
+	m_frame = frame;
+	propgrid = NULL;
+}
+	
+void ASSDrawSettingsDialog::Init()
+{
+    propgrid = new wxPropertyGrid(this,
+		wxID_ANY,
+		wxDefaultPosition,
+		wxDefaultSize,
+		//wxPG_BOLD_MODIFIED |
+		//wxPG_SPLITTER_AUTO_CENTER |
+		//wxPG_AUTO_SORT |
+		//wxPG_HIDE_MARGIN | wxPG_STATIC_SPLITTER |
+		wxPG_TOOLTIPS |
+		//wxPG_NOCATEGORIES |
+		wxTAB_TRAVERSAL //|
+		//wxSUNKEN_BORDER
+	);
+
+    #define APPENDCOLOURPROP(pgid, label, color) pgid = propgrid->Append( wxColourProperty(wxT(label), wxPG_LABEL, color) );
+    #define APPENDUINTPROP(pgid, label, uint) \
+		pgid = propgrid->Append( wxUIntProperty(wxT(label), wxPG_LABEL, uint) ); \
+		propgrid->SetPropertyValidator( pgid, validator );
+    #define APPENDBOOLPROP(pgid, label, boolvar) \
+	    pgid = propgrid->Append( wxBoolProperty ( wxT(label), wxPG_LABEL, boolvar ) ); \
+    	propgrid->SetPropertyAttribute( pgid, wxPG_BOOL_USE_CHECKBOX, (long)1 );
+	wxLongPropertyValidator validator(0x0,0xFF);
+    
+    propgrid->Append( wxPropertyCategory(wxT("Appearance"),wxPG_LABEL) );
+	APPENDCOLOURPROP(colors_canvas_bg_pgid, "Canvas", m_frame->colors.canvas_bg)
+	APPENDCOLOURPROP(colors_canvas_shape_normal_pgid, "Drawing", m_frame->colors.canvas_shape_normal)
+	APPENDUINTPROP(alphas_canvas_shape_normal_pgid, "Drawing @", m_frame->alphas.canvas_shape_normal)
+	APPENDCOLOURPROP(colors_canvas_shape_preview_pgid, "Preview", m_frame->colors.canvas_shape_preview)
+	APPENDUINTPROP(alphas_canvas_shape_preview_pgid, "Preview @", m_frame->alphas.canvas_shape_preview)
+	APPENDCOLOURPROP(colors_canvas_shape_outline_pgid, "Outline", m_frame->colors.canvas_shape_outline)
+	APPENDUINTPROP(alphas_canvas_shape_outline_pgid, "Outline @", m_frame->alphas.canvas_shape_outline)
+	APPENDCOLOURPROP(colors_canvas_shape_guideline_pgid, "Control lines", m_frame->colors.canvas_shape_guideline)
+	APPENDUINTPROP(alphas_canvas_shape_guideline_pgid, "Control lines @", m_frame->alphas.canvas_shape_guideline)
+	APPENDCOLOURPROP(colors_canvas_shape_mainpoint_pgid, "Points", m_frame->colors.canvas_shape_mainpoint)
+	APPENDUINTPROP(alphas_canvas_shape_mainpoint_pgid, "Points @", m_frame->alphas.canvas_shape_mainpoint)
+	APPENDCOLOURPROP(colors_canvas_shape_controlpoint_pgid, "Control points", m_frame->colors.canvas_shape_controlpoint)
+	APPENDUINTPROP(alphas_canvas_shape_controlpoint_pgid, "Control points @", m_frame->alphas.canvas_shape_controlpoint)
+	APPENDCOLOURPROP(colors_canvas_shape_selectpoint_pgid, "Selected points", m_frame->colors.canvas_shape_selectpoint)
+	APPENDUINTPROP(alphas_canvas_shape_selectpoint_pgid, "Selected points @", m_frame->alphas.canvas_shape_selectpoint)
+	APPENDCOLOURPROP(colors_library_libarea_pgid, "Library", m_frame->colors.library_libarea)
+	APPENDCOLOURPROP(colors_library_shape_pgid, "Library shapes", m_frame->colors.library_shape)
+	APPENDCOLOURPROP(colors_origin_pgid, "Origin", m_frame->colors.origin)
+	APPENDUINTPROP(sizes_origincross_pgid, "Origin cross size", m_frame->sizes.origincross)
+	APPENDCOLOURPROP(colors_ruler_h_pgid, "H ruler", m_frame->colors.ruler_h)
+	APPENDCOLOURPROP(colors_ruler_v_pgid, "V ruler", m_frame->colors.ruler_v)
+
+    propgrid->Append( wxPropertyCategory(wxT("Behaviors"),wxPG_LABEL) );
+	APPENDBOOLPROP(behaviors_capitalizecmds_pgid, "Capitalize commands", m_frame->behaviors.capitalizecmds);
+	APPENDBOOLPROP(behaviors_autoaskimgopac_pgid, "Ask for image opacity", m_frame->behaviors.autoaskimgopac);
+	APPENDBOOLPROP(behaviors_parse_spc_pgid, "Parse S/P/C", m_frame->behaviors.parse_spc);
+	APPENDBOOLPROP(behaviors_nosplashscreen_pgid, "No splash screen", m_frame->behaviors.nosplashscreen);
+	APPENDBOOLPROP(behaviors_confirmquit_pgid, "Confirm quit", m_frame->behaviors.confirmquit);
+	
+	wxFlexGridSizer *sizer = new wxFlexGridSizer(2, 1, 0, 0);
+	sizer->AddGrowableCol(0);
+	sizer->AddGrowableRow(0);
+	sizer->Add(propgrid, 1, wxEXPAND);
+
+	wxBoxSizer *bsizer = new wxBoxSizer(wxHORIZONTAL);
+	wxButton *abutton = new wxButton(this, wxID_ANY, "Apply");
+	abutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ASSDrawSettingsDialog::OnSettingsApplyButtonClicked), NULL, this);
+	bsizer->Add(abutton, 2, wxEXPAND);
+	wxButton *rbutton = new wxButton(this, wxID_ANY, "Revert");
+	rbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ASSDrawSettingsDialog::OnSettingsRevertButtonClicked), NULL, this);
+	bsizer->Add(rbutton, 1, wxEXPAND);
+	bsizer->Layout();
+
+	sizer->Add(bsizer, 1, wxEXPAND);
+	sizer->Layout();
+	SetSizer(sizer);
+}
+
+ASSDrawSettingsDialog::~ASSDrawSettingsDialog()
+{
+	if (propgrid) propgrid->Clear();
+}
+
+void ASSDrawSettingsDialog::OnSettingsApplyButtonClicked(wxCommandEvent &event)
+{
+
+	wxButton *button = (wxButton *) event.GetEventObject();
+	//wxPropertyGrid *propgrid = (wxPropertyGrid *) button->GetClientData();
+	if (propgrid == NULL) return;
+
+	#define PARSECOLOR(color, pgid) \
+	{ \
+		wxVariant variant = propgrid->GetPropertyValue(pgid); \
+		color = *wxGetVariantCast(variant,wxColour); \
+	}
+
+	#define PARSE(ptr, pgid) propgrid->GetPropertyValue(pgid).Convert(ptr);
+
+	PARSECOLOR(m_frame->colors.canvas_bg, colors_canvas_bg_pgid)
+	PARSECOLOR(m_frame->colors.canvas_shape_controlpoint, colors_canvas_shape_controlpoint_pgid)
+	PARSECOLOR(m_frame->colors.canvas_shape_guideline, colors_canvas_shape_guideline_pgid)
+	PARSECOLOR(m_frame->colors.canvas_shape_mainpoint, colors_canvas_shape_mainpoint_pgid)
+	PARSECOLOR(m_frame->colors.canvas_shape_normal, colors_canvas_shape_normal_pgid)
+	PARSECOLOR(m_frame->colors.canvas_shape_outline, colors_canvas_shape_outline_pgid)
+	PARSECOLOR(m_frame->colors.canvas_shape_preview, colors_canvas_shape_preview_pgid)
+	PARSECOLOR(m_frame->colors.canvas_shape_selectpoint, colors_canvas_shape_selectpoint_pgid)
+	PARSECOLOR(m_frame->colors.library_libarea, colors_library_libarea_pgid)
+	PARSECOLOR(m_frame->colors.library_shape, colors_library_shape_pgid)
+	PARSECOLOR(m_frame->colors.origin, colors_origin_pgid)
+	PARSECOLOR(m_frame->colors.ruler_h, colors_ruler_h_pgid)
+	PARSECOLOR(m_frame->colors.ruler_v, colors_ruler_v_pgid)
+	
+	PARSE(&m_frame->alphas.canvas_shape_controlpoint, alphas_canvas_shape_controlpoint_pgid)
+	PARSE(&m_frame->alphas.canvas_shape_guideline, alphas_canvas_shape_guideline_pgid)
+	PARSE(&m_frame->alphas.canvas_shape_mainpoint, alphas_canvas_shape_mainpoint_pgid)
+	PARSE(&m_frame->alphas.canvas_shape_normal, alphas_canvas_shape_normal_pgid)
+	PARSE(&m_frame->alphas.canvas_shape_outline, alphas_canvas_shape_outline_pgid)
+	PARSE(&m_frame->alphas.canvas_shape_preview, alphas_canvas_shape_preview_pgid)
+	PARSE(&m_frame->alphas.canvas_shape_selectpoint, alphas_canvas_shape_selectpoint_pgid)
+
+	PARSE(&m_frame->sizes.origincross, sizes_origincross_pgid)
+
+	PARSE(&m_frame->behaviors.autoaskimgopac, behaviors_autoaskimgopac_pgid)
+	PARSE(&m_frame->behaviors.capitalizecmds, behaviors_capitalizecmds_pgid)
+	PARSE(&m_frame->behaviors.parse_spc, behaviors_parse_spc_pgid)
+	PARSE(&m_frame->behaviors.nosplashscreen, behaviors_nosplashscreen_pgid)
+	PARSE(&m_frame->behaviors.confirmquit, behaviors_confirmquit_pgid)
+
+	wxCommandEvent evento( wxEVT_SETTINGS_CHANGED, event.GetId() );
+    evento.SetEventObject( button );
+    m_frame->GetEventHandler()->ProcessEvent( evento );
+	
+}
+
+void ASSDrawSettingsDialog::OnSettingsRevertButtonClicked(wxCommandEvent &event)
+{
+	RefreshSettingsDisplay();
+}
+
+void ASSDrawSettingsDialog::RefreshSettingsDisplay()
+{
+	if (propgrid == NULL) return;
+	 
+	#define UPDATESETTING(value, pgid) propgrid->SetPropertyValue(pgid, value);
+
+	UPDATESETTING(m_frame->colors.canvas_bg, colors_canvas_bg_pgid)
+	UPDATESETTING(m_frame->colors.canvas_shape_controlpoint, colors_canvas_shape_controlpoint_pgid)
+	UPDATESETTING(m_frame->colors.canvas_shape_guideline, colors_canvas_shape_guideline_pgid)
+	UPDATESETTING(m_frame->colors.canvas_shape_mainpoint, colors_canvas_shape_mainpoint_pgid)
+	UPDATESETTING(m_frame->colors.canvas_shape_normal, colors_canvas_shape_normal_pgid)
+	UPDATESETTING(m_frame->colors.canvas_shape_outline, colors_canvas_shape_outline_pgid)
+	UPDATESETTING(m_frame->colors.canvas_shape_preview, colors_canvas_shape_preview_pgid)
+	UPDATESETTING(m_frame->colors.canvas_shape_selectpoint, colors_canvas_shape_selectpoint_pgid)
+	UPDATESETTING(m_frame->colors.library_libarea, colors_library_libarea_pgid)
+	UPDATESETTING(m_frame->colors.library_shape, colors_library_shape_pgid)
+	UPDATESETTING(m_frame->colors.origin, colors_origin_pgid)
+	UPDATESETTING(m_frame->colors.ruler_h, colors_ruler_h_pgid)
+	UPDATESETTING(m_frame->colors.ruler_v, colors_ruler_v_pgid)
+
+	UPDATESETTING(m_frame->alphas.canvas_shape_controlpoint, alphas_canvas_shape_controlpoint_pgid)
+	UPDATESETTING(m_frame->alphas.canvas_shape_guideline, alphas_canvas_shape_guideline_pgid)
+	UPDATESETTING(m_frame->alphas.canvas_shape_mainpoint, alphas_canvas_shape_mainpoint_pgid)
+	UPDATESETTING(m_frame->alphas.canvas_shape_normal, alphas_canvas_shape_normal_pgid)
+	UPDATESETTING(m_frame->alphas.canvas_shape_outline, alphas_canvas_shape_outline_pgid)
+	UPDATESETTING(m_frame->alphas.canvas_shape_preview, alphas_canvas_shape_preview_pgid)
+	UPDATESETTING(m_frame->alphas.canvas_shape_selectpoint, alphas_canvas_shape_selectpoint_pgid)
+
+	UPDATESETTING(m_frame->sizes.origincross, sizes_origincross_pgid)
+
+	UPDATESETTING(m_frame->behaviors.capitalizecmds, behaviors_capitalizecmds_pgid)
+	UPDATESETTING(m_frame->behaviors.autoaskimgopac, behaviors_autoaskimgopac_pgid)
+	UPDATESETTING(m_frame->behaviors.parse_spc, behaviors_parse_spc_pgid)
+	UPDATESETTING(m_frame->behaviors.nosplashscreen, behaviors_nosplashscreen_pgid)
+	UPDATESETTING(m_frame->behaviors.confirmquit, behaviors_confirmquit_pgid)
+
+}
diff --git a/assdraw/src/settings.hpp b/assdraw/src/settings.hpp
new file mode 100644
index 000000000..c11c42c36
--- /dev/null
+++ b/assdraw/src/settings.hpp
@@ -0,0 +1,119 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#pragma once
+
+#include "_common.hpp"
+#include <wx/propgrid/propgrid.h>
+#include <wx/propgrid/advprops.h>
+
+class ASSDrawFrame;
+
+DECLARE_EVENT_TYPE(wxEVT_SETTINGS_CHANGED, -1)
+
+class ASSDrawSettingsDialog : public wxPanel
+{
+public:
+
+	ASSDrawFrame* m_frame;
+
+	ASSDrawSettingsDialog( wxWindow *parent, ASSDrawFrame *frame, int id = wxID_ANY );
+	virtual ~ASSDrawSettingsDialog();
+
+	virtual void Init();
+	virtual void OnSettingsApplyButtonClicked(wxCommandEvent &event);
+	virtual void OnSettingsRevertButtonClicked(wxCommandEvent &event);
+	virtual void RefreshSettingsDisplay();
+
+	wxPGId colors_canvas_bg_pgid;
+	wxPGId colors_canvas_shape_normal_pgid;
+	wxPGId colors_canvas_shape_preview_pgid;
+	wxPGId colors_canvas_shape_outline_pgid;
+	wxPGId colors_canvas_shape_guideline_pgid;
+	wxPGId colors_canvas_shape_mainpoint_pgid;
+	wxPGId colors_canvas_shape_controlpoint_pgid;
+	wxPGId colors_canvas_shape_selectpoint_pgid;
+	wxPGId colors_library_shape_pgid;
+	wxPGId colors_library_libarea_pgid;
+	wxPGId colors_origin_pgid;
+	wxPGId colors_ruler_h_pgid;
+	wxPGId colors_ruler_v_pgid;
+	wxPGId alphas_canvas_shape_normal_pgid;
+	wxPGId alphas_canvas_shape_preview_pgid;
+	wxPGId alphas_canvas_shape_outline_pgid;
+	wxPGId alphas_canvas_shape_guideline_pgid;
+	wxPGId alphas_canvas_shape_mainpoint_pgid;
+	wxPGId alphas_canvas_shape_controlpoint_pgid;
+	wxPGId alphas_canvas_shape_selectpoint_pgid;
+	wxPGId sizes_origincross_pgid;
+	wxPGId behaviors_capitalizecmds_pgid;
+	wxPGId behaviors_autoaskimgopac_pgid;
+	wxPGId behaviors_parse_spc_pgid;
+	wxPGId behaviors_nosplashscreen_pgid;
+	wxPGId behaviors_confirmquit_pgid;
+
+	wxPropertyGrid *propgrid;
+	//DECLARE_EVENT_TABLE()
+
+};
+
+class wxLongPropertyValidator : public wxValidator
+{
+public:
+
+    wxLongPropertyValidator( const int min, const int max )
+        : wxValidator()
+    {
+		m_min = min, m_max = max;
+    }
+
+    virtual wxObject* Clone() const
+    {
+        return new wxLongPropertyValidator( m_min, m_max );
+    }
+
+    virtual bool Validate(wxWindow* WXUNUSED(parent))
+	{
+	    wxTextCtrl* tc = wxDynamicCast(GetWindow(), wxTextCtrl);
+	    wxCHECK_MSG(tc, true, wxT("validator window must be wxTextCtrl"));
+
+	    wxString val = tc->GetValue();
+
+		long valint = 0;
+		val.ToLong(&valint);
+
+		if (valint < m_min) valint = m_min;
+		if (valint > m_max) valint = m_max;
+
+		tc->SetValue(wxString::Format(_T("%d"), valint));
+
+	    return true;
+	}
+
+private:
+    int m_min, m_max;
+};
diff --git a/assdraw/src/tsukasa.ico b/assdraw/src/tsukasa.ico
new file mode 100644
index 0000000000000000000000000000000000000000..f645f0773c987c58343e8a4b1d722ad64f900f5d
GIT binary patch
literal 17574
zcmZQzU}RunFfaho3Jfb$85rCc7#I{3pnL%ahIgtkJ_o}J4hDv4W(*7h0w8$~h748)
z20MEO1`P%V1_K5Lh6DzXxB>$hcz{Ww3EQ2s6w_aA`o_Bc*nfcw|No1h{r{i$(*OVd
zS1<oR@&Et-{r~^}FL}G`f56VZ|Eo?<`+w~2%Kyh6uK6EWIq`pR_vilsy`TSkRj&BI
z{OF?p$DgeHzxn3!|3U3(|BwIw|Nqec|NmD#`SyR}nM?l<|NsC0-2eao&;S4bUv1Hr
z|J?ik|K~gW{e#?z2Z}^H7KcLK0Fz5Bv$y|ezx@9{%ccMSS+D;8Z*%4X*!_$C|NpPw
z7WKb;W!L|8$7cUOetYHrUFR464=A1SKXAgQ|Ned7|A+Ry_#f0T;s4faoBp>hY5afW
z|HuC|J9hl<J$&^4f&c&iU-|$4|79p%`T6^Q(;1VB)#p!GhQm1|3tJf}{a4>{=)VBe
z?Hnin|Cd<4?*EMcAOHKEobiA8l|}zA-dy|t%*}QG&)i)5f5!5%|NbR)|AQyI{O{NM
z{(nI4hyTGnkN!tBw*H^9ZRY=_mk)r$dBLp<|Ihya4-fkb|Ns9l?rZ-Ka-fcm(k2j1
zDK@ax^`B>J`9Es^!W)9SPVeR4exXI?*fCC*8yjX8{(Ho!+?u?mCdcppjsuhbpS!pI
z|LJ?H|1aFo_`iP9r2k<P?*9+yd-XrC|J{F&-cSEs@}~b^x~2R7np5-sZ#=l{zoxhC
z|NiH9{~!GJ_y5MHZ~jl7HUIzP?wS7!rZ+52^0NA$>g#fnQun(U8=l(b;`HC&+W|E`
zwbT!S%vRRc-nz}k=6|n^!T-8k@Bb%nt^a@c;mZH*3nu@M>bm#ezxU<;p#Jy&11CKH
zZ(lUy|E}AM{-3<F`v3g7MgLQbb^m*p<ou7(QU70TqWgcQkKh0QQ<napUR?G+)za+$
z3LD%1Q6*{r8Pp`ZKz5OXtBmdboN%@IU!bY`7FoXxzswO3Ki|;u|1mq8|A*~t|5qzX
z{%=q8{=aY6^#39GDgT}7_Wbv)-S*$Te8Yd&>I45RQfB{8_qX~#G1Te*WP5}E2OM4h
z=V+?^pKEXVf19)Y|DAq;|Nl>4`u}U|%>VUzdjI!3JNz%#RQvC4WcdhW7pYiM(wJ+#
zyU+h)u8#i~Tblj%HVIOKnGvL5^hi_HyK%LH_y5DTR{sy#I{jZ^YV*I*!t#HLx99)7
z*3SQHU;P88^JD-2|6lax_x}l}9{g|bp7OsvIqCmoSLgrB>}>vTaB=v*-^u3xK_~nF
zyFl)rvh@G|Da-z^^zr|Hz}4aZECb{J9l=rmgG!gG@<`Z-8tC}d!`wiKcC(CXJ?QK6
z|FpBy|6|VX{}XJ2&VckNNn1LV7@Gd~)wcP+(#HA!Bpb{BlhZT)uid=o|CJB_|6hfc
zgP<}6lqW%DBB;EC;nV;B{|Dg>$IkrkD6jtCWNrU{y|csrtwAB+^z(o6(*Lh(+W*fp
zv;9BC*!cg=>Yo4NauzMB`d$fzVcFk7Zoq|A<xS!FKHed6-Dww(|EHZ?{-1Pk`QM;t
z3oaX6H9eQL>*@S=(9r%ruXE=A^RFP~HYl7y?gf?Or~dy3mn|p%|NjpX2Vt1_!T<mN
zAA!~#yZ`_HzvIE*|IJwy|EKu*{{KIDAvpa1Pha+bmXp)}ejA7X|7R@wZ!RJG-_0fY
z|Gd=FU%1>360eEK*kq>Y5ej0LI!CTM<>d1Jgp<?%;|>o0S6Ev9_jk()*HE<GIH`Nd
z|5f+?|KIrX|Nkvt{{IKL2^7Ada0R&?ghBP&hFAapuX_0Z|NdVP|A53nYC-khw*UYC
zum14=|I!El|1Z1$|9?Yq!~g$N=KudcWg$2p98O95Kh@v+|Np70|My$i|8I41`G2Rm
z9~_1t_hG}0UcR5ReKK}~<Qjc5@0@|U|Ad3v|2@w3|NV^Z|EDe7^?&94|NrOT`2T<Y
zo&Wzgy#D`x|364LgWLylH;7K_J^kN5{lx!}^fUj%v(NvZb>Z9pGtlxLRBvtl`TzgQ
zm;e9IyYc`3tZV=Ocl2)j4@x^=_fKB>|NrC#|2HKh{Qp0B+5d^wR{wX$$N&F7W8r^i
zIbC=@1i2F#uZYk1zdEfR?8o--ivOowz5X9?a{9mA((3<QOWXfGn!5k@eER=?;m!a5
z=U#@`z53bz|2uy{(geuupm<pN;@f}!+>`$ki~syjD)|3DG4Id+h}r|-GzC%vN<Uk_
z{r|u0<^TV)ZvFp1<;ws6?Y(Ou=^qsSVD~Tjf37G892c`(oc_OSZ25nuwCaDQSJYu-
zHzTumW|#i|+dl2Tj!sDKjQEECJKa3~x5h>OkBJNYfAZU(|MeT!{onNA|Nq5z{{LTa
z^Z);)cOl^qO2?ou1*Lb8`*!~Q|KGcK&;Qt_bN>@sul|p%J@-GpbqhG(g8T=<JO2Ft
zzxLDr|I6O||3B;T|Nl)hxBve?b1B%p|0jd|vikq)nwI}BTc`YA?C$;lU1Qt-|DBWn
zuT0JdhcB|bVeAXl?f?Hzo&P_`IsWa8wA%mk+iU-CK6~c>yor;+ZIrHqhyU;X`v3o?
z*Z=?T{`~*{&d>k<Z~OfJ|2}AY4AdqAxeb(GxBvYA|LFh!;I<k_>@YO#fWjWc2kF`I
z|NsB(fByep_x1n(zD;NUf9ae5|NrzQ|Nl=}_5c5r72q^<Jh%G)j)3t0?@Js0|DU}4
z|M&Kp{|%KbRA6p~(OL{zY;QWJ|NlQ}(f>uM75~F+?Ejzn_3Hor#q0m?sA>EUO4D5z
zPJ-K<TmSt3zy8zz|GWP}+zxUJ$n79{`@jGHLGA+OPY}KN@Bjax_yJ)MALI|1+P(h~
za%*lq{eQQm7n+Ab^#I8I%l`lGp80=Yc*6e&dDZ{_Pg?%}|I}6gQ_TEZVD5&|AoqW5
zpY#9!q!s^v_AdUP>R=Bp%P;iK{eQWn`v0O+`~S~<@emx=pfH^K=-dCf_g{hAkf8Ep
z%O8ka*1rA!f5xr<{}(^`|9=`NZ{GR;f60^o|JS_!|9{cF|Nqy2`2QcI7E}&_Fw8%*
zZe07H?PUA^|MbPsuwV86|K!!+Jh3k!?f<2Wg8%;~FZ%y~@~Zz6gYrJW+zq2a?*Gs}
z3!LBo&shAw$J_h=%K7vD|DV3-|M$9<|0cSM{}<gn`(MW0;(zC!9sjTY{||0MgVF-X
zKU@C(|G)h8|No00|Nq~2=>Pwo1ONZ`g6M<)|99{H|9|?i|No~P|NnpCz5oB$yoIzo
zL2(Kyb0d3OL23Fw7Xt&d3<8Bc$o=cU{PXEW|Ia07{r^98(f|LGmj1t9I~Am!5$1Lf
z4RZhUc2N3R{Qv*t#s5Dy_59xymj>}qb=QAe9?t)>_OAo!gX5G5?f-Xu{R1vnKw-K3
z!~g#?uKxc&;n@HGE!+S9Zv)|-|Npn``2W9s_y7MhF8}{uyz>12NvH1oFIl<vzlgIn
z+$;tLhW}DLTwwQt+Hs(828aLTMgMQ-mi|8-nE-J=C=Mnq|8Hj;xESPa2P5lZ5DmgN
z8Ye*9J9*jv|C8tazf)QZ;a9i*Z_w2Fzh>3q|LJq4q1Xws7lfIWB>wlEx%PkM+yDO;
zK7zQl=h*-M{U`qapMC}6FHkySH8RGkKV!w5|1;)*;vW|FpzvP}_Rq`e*8eBN<DlsW
zl!li6FZ3?}*Tv<5;jck%2jK(R)&KubUh)6`q{aVV)wKNo(>nv4{{FZ1{hw!U`F~sg
z1aLmy_x=BW`_vQ+cYw+rP#y;5*^NK{|6c|2%l-fV*M9i_f7_q`|M&d=|G)Rl)&J7Y
zw*Li8b^fdRyZ=v|Kl}d<XgM%_Bd88r@&EtC761SDf&2k-|FZwz+NS*98x{}t%l}CW
z|AX+1u!6rJH*czJ`mZ4(CkbM2NhtdNe=5ZN_lm3j|DUxS;^&^3|5w;L{y$n>2Tu2(
zavqd+=iYhvf5D@B|0iEO`G4_?$NxcT2!ug?0M!Seat2iHfG{YJgUVA-xis^|=l{z;
z{QbY=^{4-v|3k`Iklf7Er~ZGMFz5gOi3|V#?*o-Vp!~b~|Nq_v|F^{?gWU}(A3^w9
zNzZ>B!(_ewgrr~nAyKPA?w=eG0}21B%l==>FNcIZs7*Uz!T(JzzW?8KO#6TI{vB|e
z3{+2n?A-GC|Nl8RU;SVE9#YnW;sE3aP}vA_KPYd5_{bRK2T)vq^n)<SuONEYrw`yT
z0=s|WlK=mwulxUh3MdaR`@cOt85;hO^z*ZK;eQ1&JHL*|sO`@>XM)m#L5+75#Qif?
z{J#aRFBU=CgOeBh-y0J9|NoT5|M#p~3Qj|y@CW$;gkfb6hz4PhyFu;)VNke(`~Y$v
z$PXYsNF0Pge2_TE&!BQ>-ptwm_hjY$|37&N1Wy5_pVi<t-1#C<+E@z7!=Q3#=IZ}O
z${tM~rj{%I&)WV!+tlq|u1z4s{nJ<cKa&d!e~^FY{=b-3@c;kBCI1gL)&IW@Z6AaD
z0J49<ty|zWG02@Dx9|Q1X_JED0E9u}Aax-3g4_?HLH-7@L2{rz!n`Fb|NodU|Nr^o
z3P?K|<cEnXp>@FO|7UaZA!!-pc2GNe=JNkO=26=vBqTil&sz8YW&5=MP7;d$|Ib|U
z|NqS8|Ig%>LetM&aGiWBrwm;7eyH#LfBfDZ@OTYq`~Vbo@iqD2I03n3^P8Xl*F1jy
z|L8x+7!SxlAh&|t4@xJqAHD#$D?ogZI7rXJL&yH#ZkY~FAJ>a2{{Nq{1d<0Pg2HYY
zI1QZ0DS(7Ms163T?`AChALbal9hB~Oq*VL`<=Yk;`~UxEF9X+EXR`_+?(YS)WtaZH
zpIZ&77bmRve_+O3a9bGECpq}}*Z=4MpZ|CM{|EbF^UF{F7vH!Jb|WaCgWL#mE2y3Y
zxj(q27+ha~+zkr<-LF6VKUCKNu5&=;{#{VHF>yX5{Y;0r9VEU#JOBUx8H@h^?+2AB
ztH5C#W)}r^e};qmrT<fx{{P<A`~P88BiP-Svx@%z2c^FWEC2tWxbpw)0#Mny<p2N1
z$^Xw()c-&8??2cN2fzOLU+U`p|I~w*;54-B<M03TE}jFo+dy#xay!TmAUx^7q5lnw
z7lGA*+z*ml-q`W~f6tu%56YYVe{bmj|GvKS|Np)@Q1`EdxM9lD|A)ZtU;6)l?{auM
z$lEL&?0!9Qar6JP7ySP}d(r>nX<6WOb~nHJ|Nn^~ze4iR{eqhR|N9sI|5w%f|7cX&
z|Aq6H{0E2c&;S27=U4pSGIb`{KOlEbIJ_TRMuGA&%nzWvlA4|Of7Qjy;ITtcex1B_
z-T#xh75^WVw}R6qsP6gQI{E**_DTQ0PhJ3NOHToX-_rkkk~9DRp8=}VKzJ#bZKLl~
z4N5;CymnH@>;Fp^|38qP4i5kCO%wjVukQK(e=?~2TK)f1P51x*ZPWh$?_BWzf9Jyg
zOJXzsFFADd|K2B`{;$X{`@bu<^#84YkTf*q$O&-U2;^oE2KnLS_y7Ns-F^Qb{q^fV
zC{G{y`Tu_rXv|^4EQs4Dfzs)U|L@yp{BNi%`(J!!$NyQCW#Bvk>Vxe~&H4X-#yW8O
z^Z!&(94z{8sO91Zaytn7N4rk`|NsC0Yb)md|2ugmI1X;+R{j4!X&D4}&HewXu;Ksz
z?#2KAw=eqtzhT<{Q#<zl-}3JJ{}K<M|JO3g{-3#i_y75S|Nl=rdJG&lAh(0U8AQ)p
zwf_I&>;iDQ0_ExKti1nUKw&&##sB}HJT_s)|KEK}{&&xv^FQ(b|Np)>kNm$fWdS%W
zLGC}6QwlCeL45#_`|mVQ`LAmd4R=4t51;;lav{hUpw7mL|Gy{C`2QbN225P=|9{`2
z|1UxQ>7M`pe+LN9`G2yq?*EPd|NnQER{p;cm-Bx`Lld}<)qmg!IRApu5(tCbKeuht
z|CRa0;562A;LQKUsiok2^?$<R|Nkc}{eQ1#_W$C2+y96C|NlSe|Ns95i{}0ZjYEL@
z#C=QuUoUM0rx}pjLG92LX*K^%11f|;?uOxs^BSA}|Nr{`?zhKKPyGM?|LV2>{}(L%
z|9|4#|4%bZ!FK&`TlD{b%Yy&^YbX6bwQ2MJxl?BR|KC3Q|GB)%|CiqX`oH+r<Nv$f
z{{V+IC=VR@{r~^kyypMQN=m{0n>2s<|NlKp|Nrj?rR^2}uk}p(UvTyG{|KntLG+Zy
zc4*jx($%v64=O-?Lr}T1^#A|;hyOR0w1L|{Ft@|#=1pDy^Z&p4-*Ef%|E~yN{Qv*-
z>Hi<|SN(rl(F939EsOsDZ=Uo2Zdud+%^Oz!e_Gk`|9`{G|6ArR`+xe^|NqlZoCBAq
zpmJvYy?6gF<hA@?S=;pg(*OVeSJt-w|KGjf|Nov9|4;VM`Jeje>i@X^|Nr~{|NlP}
zly?5V`+vHz8<O@x@jrFZ|Lcui|Nox@)tnGVIVWXKhPfG;)(s3>ocI6d|D^x_|Hu4)
z`+xRhQ0)lO10pXTSn>b=tvmn!ui5hdf8X5y|7)lGKQXEM|3XmzsBQNDb0rP`pZxy+
zf69^5;PFFH+F82u$p6oclm0JjYWu(D>W%;RtGoaI?^^u-a>vB~#lK&J!#(8x|Np`N
z|AX0XXLtYqJ9E+hzq6M9|G)jf|Nq~<{6BYfJIH!4e*gQ`e|0NAUSxM8v#lq!y#|Fx
z<p2NwQ~v+|pZMnX|BA(P{@+-z^#6sPhX4OhUi$z4!ma=RFW&$EfB(7vzviy`KR+f9
z8ZWc{ADg@S|NN7ez;!gp_sgd*|Np;z;s51bUH@lHocaHM?~?zAx+ecGdVUWa-k>lK
z`2YVu$Ud+iHZA-Af6KoA|1Vtr|Nq|8|NmdT`v2%8$o-$d?r)zr17$oJ+3g@Um#w>Z
z+W-IHI7s;a|9|ZN|NoOg{MWbt$M&}TUzb(!|9|_E|Nook{{P=R`~Uxz`TutZB>(^4
zG##9#ZWVU?KXUW_|5bOMfYZ>j2_SXz{;%)q{lBxa{r}CT-v9ZJuKo}I{~wM)egMTm
z^#A|=YbSR9|33v(hk@D;i~j$gx&YE9nmXtI&sR78n+3*##|S}g#f44xZg~xIJJ{X-
z|NoEw{~w%2L1kOampA`&mM;CjqO$G(|E4*RyxcV7|J&5+|NmR(|Nq~-<o~wjiT`IG
zJqI3l*<Cx~|NrLs{};t&|36pN|G(+{QE)i}axW;a#z6f6;)C43yuAzR{$>CFPXy&(
zs6Qqz{oj^b4)1T_ayv+zvpz)z6bB#-N<%QefM}2y$RD|&^tETt|Ng43|37Qz{C}NN
z^Z$SIg8%;;=KX(DGV6b2K+XS&$G`sHklX(Mf7{&u<yNl$n~t9N57G~cQ;^$1Gzf#(
zptKYA_TK-;6X*W_KV{MX{}VxVKdAlzl~oJ>-)`^upOTV7^qgM6-Q8z1p=k%??$rPP
z!FFeX-2MOme;7X-l*UdS|DRu8{eOF2J=p#K>*xL79@F^WE}-fE#-!%||LbS{uUxzW
zoF+kG42n;XnV@_IqCs&03jet6&^{Na?cBTa|NlOa`$2fl|K_4Z8&KGig5&;u`T{Z=
zl#W1t0l7Wn|Ns9WHVA{_0ObB0P@Mz9PoDhmYv}#|zhUnGpXF2jyQta!Uzk$zf5p~4
z|3P{|W<`O^Hb|NT`2!UGpu7Mwx3;_e|NqILdI98i5WVRC|4H-yZ)&cZK#IFzYP}CH
zsVo4w>;M1%`Tzg_&x6t+_rfs9{UEm${r~?T#4i8;|G!^N<^P&%XZ{CmS^M9lvEn~S
z4wU9V802199Kieoa)0XEhySmG+Mb}Wp9mTQ0j2-B|7T~#ljU}pACjIQe^~qf|Nqke
z|H1A6(Zx`Ifcyl)AoqbVEKWSHANdbb1M*Mw@6X`)0@W#?v;vAtP`ZI(kRL#Ps@}Qj
z|NrTrG!N=`E&Knwcl!UyCD`jJnA?b@vtM6$*zo`V|HA+O|AWG}?EnA&AY1|!1BrwD
z1rtmC|L1?$w-^6G=_~Tr`~RT00{I107J$+T%r7ASfZU$`|Ns9LeN&+BU;2N4McLcF
z(iB@_-A9bNg4gHnf&5SfDx;D70dhAe>_Kh^u|a99`v3p`?nih1?*hfy$z%Uhy4(I&
z{{Iio10X+v${-L1#TO_|WnDe>|Lep#|BtuTz3r*a3@64t<fw_dxOq)IH0(j{0l67Q
zgW?6m2IUu!Kgv40{@-nx_y1$v%>V!Er~Pl-w&p)9zCi8<#Rn)ZKz?^9j=8qJvzDsi
zjmv-OCsu|Oe7f@m6c-gxzktFUl-@yZ2l=TSR0p*${QtiR)K*>e|9{8Q|NomN{%@W$
z?LSN{DBpnm9CdLOcq|i_eY6r!y0k4f|J#$#AUD*3(h0Qu2|K!Betlk^-sZx>g2VZR
z1!qdi3U-y06zp%QPnejS%kHyjs(sv>D>qWV+_@QZW&41*9XU+0Pw&!gd-0;W@%iIv
zF*_F#T|Xk5K`t9K@W%L`fdNEwBhy?A3?T7;RtyXb^$ZMf+5*D=Bf-GHpwGbYMu35V
zfgeFX0Xc-9fdNdjBj^Vpadrj<FwKmEW`v3}Le?!YAkp9zOpFW+U>al=6gS|Y4}ioO
z85q!Mu>DB(fG0v285qDcGXuj9kUnMxhCd*h9YOyC@%b4Tz_dIhycj?<$N}~Y4F5rN
zJp;r41CVh0|A2vk9Tc7)7#QS1^dANWdl3Df`44D@^#A|&|NsAotkVMd$pLwt7DxbO
zA0F(nZ6dqR?w-Z$+phiRKmY%~{N)e-=Y9C_f5yAJ|6_Mg{J-VG-2aDfulyfazxjV)
z@0b5c{hR);KfnC{)crI5&$)W$|Hd~T{;z)Y65O9W{^#$1#T5sy@$Y-TP3g>CemvHq
zNa<LqEfC*z1-!OO@W_k*HP0UXFTAko|Dq$a{vW-%^8bc|6aNR)t@t0%_u+p~&x8Lt
z)0Y09dvMwRO-~>EU-|GZc#HwGW?<f_6aRJ7<3hCk-9V`g#SUB?OG_P%Nw!v(+?PyW
z&%fh*s@n8MYyH`c)&WVrrxrG*{NH_K#{X@nX8bRiz2<*V-?RVz{qO#}R&Dve{@9HF
z>-Ww4ADEl;f714C|7Xpa|NngF)c>WqN!LqVZJ)a(hj=h3DG>~VY!fTLWp*|{GK`G+
zKyDNkmv;o=I#cua+ib1=w}(3X-?FLqe@w%K|2|E}|9dr@_-|jh`hQ=2{Qucm0snhI
zYi?}J{x5ZQ{Qsn`^Z&Ngy#I@Atp3N@SiUjSGjal%i4RY9@-08;=K6o3wcUwW>rlB6
zWs_J>b(@20?VSH_a`X7VG%ff4gvO@-bB~<*f8y8w{|A2m`@ih*hyQa|uKmBbtMmWz
zl$8G~++F|ga(DaxytecItH%ESJ3PJr&vA77Ulp9*Y-bS~7HA(0%Izr5P*yPZ2MKgJ
z1syo$;`)D`jq}fP184s@EvvN=+6MnuwNCoK`|$DqN8Wt+fAKG5-2`Zy7&Z<A8qWZY
zhi!fQ^#AhhNB>WYi2HxPw*CL#NsIpPij4oiF*N3Xg=@f*IN#J;6OsypL3SbI5})X`
zL6(skGu=WipLBBmzu(^Be~q=<mgKStcNU#`{eRud|Nr;=g3L{V`tJKa{ro@U_}l-J
z_PzVR@$nDvxEyF4chism|Cc`g|9{4wTmP^1%m$AwKdJBdzdtMg|JLxt|C<t1|KD!t
zjzzW`#GW0M@pX1WmG4~t)bGcfUH-4LvHPEGWd48QjSv49T>t-n@xA~5w|#}I#{l_x
z@`;!KqlzB<kIjAeKeOvLIKP3$L^gc-|9}4d|NkfMee(Z0Xub;6Uz)u5|Bb4e|GQ!n
z|39p({l6wDcQeRNWPG)<_5ZZE@?8t!i~r9nEB-%W?(F}w&z}9i@y-ALD<A&<zwY_}
z|2uy|=2t;sz4+dT|5Yn){cl?H@PES^$hu9C_;%2k(&zvGXIy;w|H{lY|Nl>04j$`$
z-PrqocXaaqFHPP5uUEGJx0ko)K(e11G)KQ7xAAv-Mb-a3d-wj|xn}+U1$S=!-}USN
z|IJ_i{|C)o?EQzBzu5in|NmY8{{IKjpm{M62KgT}1_~12@aD_^bMw~x|34KnZ~e1(
z?*B8%dH>(lbpQW5aq0hfQy*uT{q_v@EZ@85|Nk>_$^X9c^8eRYZ~4EkvFZPmlL!7!
zJ%9TDhS#6}Z~piVJP)@8<iGcjxzA~rA@rg<|Nk$#`~Uy?&ycwZ(D--H!F~Tjd_n7U
zK>ch`yM5LF>&12dAC%UE=U!JORm0l{Ap1Xd&jHUv9W5;X|D<!;|2<I&|7&_1|BI?B
z{<rt@{XgUM$^Xax{`<f6=l}onAO8Q}bMXKFj$Qx%ckKTEzkBch{}WDp`9JyW)BjcL
z*Z=oON%}7$FZZ91l?5`^1?sm=Uitq?Ma%!Y`Jj26#s4o=O+IID=&KU#<dqHzhX+lQ
z!S4FhKH>lOp4tCzq-6hJTwVFUVCIbf%1Cp&=8@t5SHJo8f9do8|7TwR|9{4n|Nj?0
z`2WB8z}f%ehKBz+M1}rK>1h2At*ZDxaUH170-E;(`G4jA&#jaH-^eZnk0D>Ko%F9h
zupnekM&WAE9Q%cmHn3Y?gT~{gEdKwnpyL1btla<S{{8>I>dxK&nNz0zPwnsi-??WO
zI37Up4oVwazWx8d>n|v6{`%i^^wj^d%{%`0UAhQXv+Vk{|34=#{QtinH0QbM|KGj^
z|1W^%&n7MU|GIVh|D|!&nX{79Zq1HK_T7{U8b@CK|7mRpczpADW!wMzWljH&+`A3V
z+lT&u*5rKqzx&63@c1bxuY=}kKx5V*44OMbo{t5k#T}0y{l8Y<2A;S6KNYn0X664Y
zr8VF=oqv;;{9h1XJ#~Ic;fX~td50Fp6#V}`ZN>iwH6Z(!{D0fj`~Pj@g#X94ZUT=N
zg7W;<_wV6zEc>8y(;#<%(i?~dxd$|#1j2`2zxjW9@#_D#Yg)ke{htI{JG1)#z3N7A
zne>0^lK<1<D-W;BC@+26J?H-f?~wohXD<7Hx3UF1AN;v(>i^Ge)Biu6z3l&~H*fx*
z`uFdD!`$iMIjWtXe*WL|>NR*Q9Aq~LuX+9I|Hjv^z+#7f|M`Dl!K(k?CoKB^3^XP?
z2{g_GTEDaG|BWipdL7Vw=d%BEk}J=*_(gc%tn2%Fv$W>_j|p@BKd5K{&$EASoB989
z`}F^BTc`X#ef7rwlfVD{?`&%OfA-_o|9igt`oH$k18_Wm%6w3{Gx6Yo|Euoa28Ykq
z!^i)>Zk_!9YwP6yADVjpgXXnCVGCM=c?~oV1{wpHvf}^rxXSZdqM|%ECQR7$rl<e^
zo0bXx-+;=83CsU~>zw=lTg#OHpDMclZ>jJ6zyIyW|J!CS{=a|yW^h@%`1&<)x&YaI
z;_v_e^<BOH_k8*KfAfu7|Mxev|Nqnmns;3O|3&M>|EFfn`~R|kHh8||GHCvJDkv_N
z{a=z+I~SDqDoc{f-XA~m|J~&2|39}({{OXo_Wyr<i~fJ9>HYt|bJ73T)f4{jK7Hx`
zwD!LL=O)ehf9~7&|I2RN1dm~Y>Y{DeZ~tF7W%~a^|Ni}-H(}cUx1BTp|L<S+|L=rl
z|EI57`#<5zvHw^5W`Ohe^@`U2|EH|{|9#@3{|nOUIzje>@T-q^9)JJ)<Nv=i7ykcS
zyA8bF@O^pP|Nq?!|Nn2F_y5McrT>>LT=M^FLGAye=P&<Xa`PUzJOZW5^(#03-?CuQ
z|HbF7{=Zf;@&Eq`%l_Y=w&Z`yk;DH%V_*5ZcK!#=LxRQ}pMln*OkeT;-h_GoCuY>a
z>%pZ578cEUbLIb$_b>kc{r2tu{~Ndde_Ocf|L3MD|Nplx`v0kA`u|;X=ly?I)A#?}
zl8yhjK7adv&&SXI4}Aaq|G@N>|F<q%`G4bvZU6uGEcySufARmiE9d`5{QCJn`2X+!
z(^jvA%sWnA{Qudc`Tzf4y7m9+@iWg8a!TR-Vy%!6m5{^xPR0NK{lD__v;Sv5zWM+B
z!Gr$~cCY{c|KQ30|L3p&|8(l?{|EBx|G%u8@c+n_JOB5*dG~++lNbN*OkDhb*^Jr$
zFHc?k|HhO>|C=7%f{()nzkc@r(AstX|83dx|NrBs{~td9%?|(jfBM$Bl?<Vw%%HG`
zVa<ZvFwpo3Xxt&`<D38W*Dw5^-P8I1?Tpp`|Igm||KEgV|4*k>{0EI~pPIA!|MrK^
z|L?zj|Nq0z`Ty6p_x!)yGU<QK)r<e5{``iIzbD+g{r|$eh5!Gr-17hbhMoU^u3q>5
z&%JB^Q)}v@VD=)@?$<9K0gXd}+yNTHN%;Hwf9loC|CcXV^Z#nc-2dOp`~Ux}n*9H5
z<J|wVC$IRw`{?!m&l_g`pPy0szxUWN@VGf>%oa2b2O2xCx^nsd3((vEXnuXtlK;Oa
zF8IH>rtK)QoyhE<M`r?(e|-7^vLECQ&{zy;JU0EukN<_Y?){%Ud&&R3C9VJe*3J9B
zBc=0ydC{EzPb((>FIlqkfAY_t;IVYr_!(%<t$+L0|9?Ps_k-5&Ec^elclwnLH8qCF
zcA~SRK0j&)jc0+z9zkO%Fd8)01sWsD|NQy?>^Up`pXs0fKPoosf8V;z;Q18Tcpb=o
z&{%5H?;rp7^i2nsXP~*j58YFrZEmgxb;;1JMB#fMTOghL_4y~zSPy9Y4TM2sS0D@;
zM*+Db<;COw8TW4dkGX&Qf6|Ay;JHyyx&e*3f$Rr`fA*bg|G!NJ&FL=x|E_21^X(O-
z@cf2iAr?;dtBXeEUteAYje)?%azNuaAPgGEDfs{If7H9D{|kP6{hxmC7I+*GH0A_~
zGZ0St_4EId4O{-dn>hEyrH0luy@l!0SggS-RP^eCVd1-{w?N~1AUA;A0tyol4I10Z
z*|+Ea;bq(ZpX!?Nzv}+2|Ddn|xdAi=mVEE#w^@^V7VK@Vwwqa>#)a1+Jd)Wb*9qsn
zxmI8K^Yh)ZzrX*%#^DMsoV#?oWzvbSbu-U@Zkm1ma##O>s+(7L=KTEpDewFHXAu`x
zlDI1hk0Tfu7&4!oH7@@2I-~B(=e7AC-?m2XSgNrqFHi1xUa9JV(o)r(_4Q(*t7h`Y
zzrEp+`0zN<^9er~80>#AF#P{{fWiLf0S5V>4GjDr85r0vKrr(G1_l^r1Pwueumb}F
zBP<bvh9_VcG$sO)f55=N2*Mv27??r$2Ll894+aMQKMV}=|6s!v2bll=|NQ?yXg?Wf
zSOR1oBLlQc0Hx4E1l+b1mX!OiB`W$~i$UwZJ%c@{AMu|-N$J11hAO!Isbi`3-_la&
zzp{eye=|KJaN9LZ+w6a#soDQhSDXL#hQ9ypEJ8u;|No)Z5&tVqUH&tKhW^*~cLTSx
zwL(JvgW9;d>2d!x3v&O5yL<gF^$7j%l@#zl);9&5->ZVt|JMf=fZN%i{ywO!Tbi5n
zzp^Cxe?m?vsBHb;XKVd`g^l(9&9;vJr#pIr`|a%>q5r3Ngn;{|8@+x0PbmriKgU1y
z|LmyL|1;t${x6Kl`@b_P@&BUOlK-=kQ~&oCrvIN=pZ0%dO6mWu@(OUjY(-l3|Ltkn
z|Cgs${|B{M7gtyQ-&$SuAJk_A^>0A!_G8(V|F7qk{XbM(_WxQ*&Ho1_HUB|l7dx7(
z!D9tUW&PlC)2DX*|LFYZ|JUa<g3HovRc-%oRJQ!TTs`ss^XiWOUn+b5zo?%0|7XpN
z|5`H}!D9}fHaKW52-F@2^$mP>cmH=^GW~z(s+s>iwoL?&5oJ$Z{XcTY(*NZv*Zj}j
zvkTlN_dd4Zf5e5A|3eP#`=5Ps9e6y4f5&Ce_|Sj;eeeH!Hy#J~V?lk&fZo^tmCoG#
zFL>_jfA?z_!DU?j`E%fQ45(gDy>tD4<&CTVgC3pvAOH5o|J28){^z{D{J-ech5uo1
zp8k*e{OEt=zkmNhWn|gQ$Nw`vz5ZYJ`NjXVzkmOi{QV1VM^0_)_&;k>&wo&xcE*fZ
z|5tQ${omKn0v=}omD!7@%>=hMK;v2)cTE02W5zOY`)}InHQ@5TXXkeCIM1>LEB<d=
zw&Fji4FqZ%F4?f<|F&&A|6gzI{eQZ1`u{7PGyb2MHuwMS3Df_-Ztng6sj2(_%eHC%
zzqHNx|8ml7aGUqU>{b7-PlL2u{`D;W|8nMv|NlU1(PnS_e`M+E|0kAi0ryEkeSz=G
z)_~h2|5k7P|8LW-{~M3Z0FQlv`kSkcFZqAu#!7I195ns_8V3RO&nNDE`M-1b|NpIr
zPyC;8@;G>$4%A25arij6&9?i*mH$g`-u%Dg#vO3mW!Bpp;BmAmCtrg5@u0pYsDC-*
z+W-Hcv5<wge}Vg;pmD)9PoMqY_WZ^F70>?s-}LJ1|8=1C|G)nJzk2M<|I;_mf!m75
zuHX6(YTts|QQ-FFjT_*0(94f^{vUnw3f$HLjq4oy_wWCOfB(VlE>K(P_wS#e;bRbH
z04)&6Oe?LeeR@0V*s0L!?342@zkK%dXIXg-ND6|vN^5KTN{*d67Fu1Mef;^IpT922
zNI;}OB)3j_X+nZRz_DZ5)zzWL=Bq88zE(p}fgL0V!UDPi|CyKsbPeVwR#XI;n(7Fc
z#5n8n^Md3+Sl>fel%HSE#A(W<pFdwLn&D((60^}nUs+fbB+K*P&_hp*pMTcXAHRNr
z!Sl1mQF}~G<Q45f^75ia9(rQIk6yg~`SbPN^Dlq?eEs6gx;-(@R?cfc^5*tt9=ZaL
zA3uKm^XJ{Lu*#o5Uq3v*W6vHxD}N`De3XT?<Mc}}Ux4&Kt~z)6=g-%#?(NvKXQS1o
zD7OFq88(MItX_WO_3PKKe}V`w^>X{3JzG3u_K5ud&$?xg!-1KXF1>vH^Yx2|4<9~$
z{Oae=6LNd@?D6y8;{ulV-E5W2A$jTN>nHawT)6PyZmud5!=62RVtn>Q3(5W8yl2Z6
zFSk@a1_tRDFCIR8agmdeLw(VnJ$ttJ?1@&fXNlUgagV?A&l@R8OCS!on1AKxjXk^e
z?DE;O+1ke3bx+Kmn5g$Zf4&3-z|WsQU%&qO^LZ4=0ekjX*jrlfiP^Jp^TD4#pF^a6
zzW(|1+dhzd)Sf*SE}M<^MD5wKW%swA(|*2w{`2S0XU~8B+_xuY&z?O|d-m8HM)_@v
z*|TNK=J!7*|9t)I=g*&)Zv4EudCMk<yan@yjhjL8v5_wquKao9=g*(XuW!!WvS;)9
z%^>|Q|202s-Lhp@?5?=$Q`UpzZ_fESee<q8iyGHK<o|#D`{~G@m|a_TEc1JJ<LA#6
z%dbW6*>SNaZ_l31dp6kr|9|rKx4)kcZP~SDZp{AYuYYb|zIxZrrk<Wfd-iPo{6_2l
zf2pFL3EzJo{<vqWcij8u&v(q(vEx=xPuISqf4=;EEB^ogf7yu>`&*{$-n++p%l79t
zH_uqt($mw^yyM8xL!Y%l3E+R-#EBCpHZNNj8^3wM_09GddwP0$TDI=lvnLWP{l66?
zKXGEqg2?!Ykht85Ao(SGcJ0~X4w3)g4N)+0;)1nGi^0+pXYbjwIS?xSzo388q)8Je
zPMX-;T;D$tq@a1vp3N}b|NsB*m@o+fx+XP)&04iJ$`+;@M0fT<<n#8gZJ9K2V)N8M
zJCHB}7k7XZG^~x^vZiHXKd5Dkkb|(=Crs+kaq{+c&uD9hh=9l+gP@%Pnvw#wRp9Lu
zCbSj`g!^Aj()fR<rulzAN1Ok#rUCy=JU#v^g!%oqt&REb;OqTA!8`T8XJO(0s*L3S
z{Wezrr(4<lpJV0xzc<+Z{}k`w|C2(3{;zlO{J+^H;D2*?(*Mrjl>hS*a{f=u&HcZ=
zzW)El;>!Pfs_OqAOw0LyEG_r{k(}cHNArsQU&}53f4jK;|N6$N|BGf<{9nDa{=a+O
z(f?brTmBy|ZTo+^tmprYs@DH^OFRBwtm^uIrMmb3`I?FU&)3cVf30@%{}-U~`ud*#
zPwFTBe^Wo@zucTH|6Ljz|EG6%|94$5_kT?HuK%TLHvBJHu;YK`_MQJjuB`lTzyJUL
zfVK<&d5^yOUwi80|LmJL{)fN0`M>bx+5bVeU;U5#@EY6~1tn2Xp9Iu5$$Ittf7a($
z|4TnU{Ga&s^Z%4DpZ}--`SBmr-vsshKz+WP-#`B6{rLl4X8`W^eE;^p_{Zn}<v+jw
zFa7lkyygPb4_VOE{(n(V=l^|u)BmrYIQ9Sjo)!Q1&sp-ndF9IgGgqzo-?(Y}|0(<T
z{a>|w#s8)2*Z<$WX4C)m8@K*nwsYhEg?sn>-@IkV|4rNW{y);*_y1OB|NjdOlmFjt
zobvyE=j8vVXUzZq7PMZsdBXqKZIl1MX`A@}Rok@x?^>q*f8RRg|C^2}|KD{^|Npvu
z=KrUCbN;{Ynhzc```9t<|JTlG|G#!Y>iHjSGyeZ+oBRJq|D6ACXU+S6WY*IE*JdpF
z|FeJL|KEL!{{QJ)^#9Go#sA+=T=4%NXlx3ELG}L>&^qtc|3A-P^Zy5E@4|}J|9>uA
z{lDq_+W)&REcn0R+^+vUdk*}cy6?pQ$$M`9-@5d`|J{4f{%>0L=KsXKZ~mX(cIf}D
z9S8pZ-*fnX_kn}|`%aztKk?|1|C5d!`9JgEiT^zpFa2MB<k<h^$BzBqeCF)`eP^%z
zUv~G-|M^$n{-1F2|NqIS{{NqQ^V|QW&mR5X{`&R*?XTbe-~8t7|E=%d|6ls>)Bjbk
z{{LV5?*IRdZ~y<_^#1?<bszu#-~H*+|2<!S{@?fg_x~N={{IKf2Y~jG9yovf|EY5q
z{~x+@@BjPjH~)XTb>;t=w>SQuc=GuFf%hN(ANct3|B<iX{vY}J>;Iv@ka2X-7%FId
z4>ZOE+KV&<FvI`<>~_vGXW3fL-f_;@22^tKn6U9Ho2w{sO9?Xn|Noy+h>uA!=j@?%
z@iOuPod5re3iHm}dv(#mE4$~nOUwReP>adlclgq-jhBxsn5<C3!qA-;Yr1p)rp;Sc
za!jr)RTZgimP=w?wr95mSL%db19dU&M*TAfFCM*g^wNpyDdl=v8dVKT)?PSpWy9IJ
zrpaYGiXAPjhPlVLonMpKlh$8R`2Y0D8EwT~+t+8-FL#(Uwe!E3-`45VG><KgTkX1H
z>8Y&$|6Kxn=N9NDq`13fOa%3^9fLwcg6CNId-(L#fE!cZ5z$eetHJ{9^Fg)N|NsA;
z!XuN7(!H!fzJ0*Xz;J_|f#Co%149EN5{8tGU=rS61kIy^=FFKH7(VbbF#NpFzyJU(
C4(I3q

literal 0
HcmV?d00001

diff --git a/assdraw/src/wxAGG/AGGWindow.cpp b/assdraw/src/wxAGG/AGGWindow.cpp
new file mode 100644
index 000000000..024124ece
--- /dev/null
+++ b/assdraw/src/wxAGG/AGGWindow.cpp
@@ -0,0 +1,124 @@
+#include "AGGWindow.h"
+
+#include "agg_rendering_buffer.h"
+#include "agg_pixfmt_rgb.h"
+
+namespace GUI {
+    
+    BEGIN_EVENT_TABLE(AGGWindow, wxWindow)
+        EVT_PAINT(AGGWindow::onPaint)
+        EVT_SIZE(AGGWindow::onSize)
+        EVT_ERASE_BACKGROUND(AGGWindow::onEraseBackground)
+    END_EVENT_TABLE()
+    
+    AGGWindow::AGGWindow(wxWindow* parent, wxWindowID id, 
+                       const wxPoint& pos, const wxSize& size, long style):
+        wxWindow(parent, id, pos, size, style, wxT("AGGWindow")),
+        bitmap(NULL) {
+    }
+    
+    void AGGWindow::init(const int width, const int height) {
+        memDC.SelectObject(wxNullBitmap);
+        delete bitmap;  
+        
+        int ncheight = height, ncwidth = width;
+        if (ncwidth < 1) ncwidth = 1;
+        if (ncheight < 1) ncheight = 1;
+  
+        bitmap = new wxBitmap(ncwidth, ncheight, PixelFormat::wxWidgetsType::BitsPerPixel);
+        memDC.SelectObject(*bitmap);
+
+        // Draw the bitmap
+        attachAndDraw();
+        
+        // Request a full redraw of the window
+        Refresh(false);
+    }
+    
+    AGGWindow::~AGGWindow() {
+        memDC.SelectObject(wxNullBitmap);
+        delete bitmap;
+    }
+
+    void AGGWindow::attachAndDraw() {
+        // Get raw access to the wxWidgets bitmap -- this locks the pixels and 
+        // unlocks on destruction.
+        PixelData data(*bitmap);
+        assert(data);
+
+#if 1
+        // This cast looks like it is ignoring byte-ordering, but the 
+        // pixel format already explicitly handles that.
+        assert(data.GetPixels().IsOk());
+        wxAlphaPixelFormat::ChannelType* pd = (wxAlphaPixelFormat::ChannelType*) &data.GetPixels().Data();
+
+        // wxWidgets always returns a pointer to the first row of pixels, whether
+        // that is stored at the beginning of the buffer (stride > 0) or at the 
+        // end of the buffer (stride < 0).  AGG always wants a pointer to the 
+        // beginning of the buffer, no matter what the stride.  (AGG does handle
+        // negative strides correctly.)
+        // Upshot: if the stride is negative, rewind the pointer from the end of 
+        // the buffer to the beginning. 
+        const int stride = data.GetRowStride();
+        if (stride < 0) 
+            pd += (data.GetHeight() - 1) * stride;
+
+        rBuf.attach(pd, data.GetWidth(), data.GetHeight(), stride);
+
+        // Call the user code to actually draw.
+        draw();
+#else
+        PixelData::Iterator p(data);
+
+        // we draw a (10, 10)-(20, 20) rect manually using the given r, g, b
+        p.Offset(data, 10, 10);
+
+        for ( int y = 0; y < 10; ++y )
+        {
+            PixelData::Iterator rowStart = p;
+
+            for ( int x = 0; x < 10; ++x, ++p )
+            {
+                p.Red() = 255;
+                p.Green() = 0;
+                p.Blue() = 255;
+            }
+
+            p = rowStart;
+            p.OffsetY(data, 1);
+        }
+#endif
+    }
+    
+    void AGGWindow::onSize(wxSizeEvent& event) {
+        const wxSize size = GetClientSize();
+        if (bitmap && size.GetWidth() == bitmap->GetWidth() && size.GetHeight() == bitmap->GetHeight())
+            return;
+        
+        init(size.GetWidth(), size.GetHeight());
+    }
+    
+    void AGGWindow::onPaint(wxPaintEvent& event) {
+        wxPaintDC dc(this);
+
+        wxCoord width, height;
+        dc.GetSize(&width, &height);
+        if (!bitmap || bitmap->GetWidth() != width || bitmap->GetHeight() != height) 
+            init(width, height);
+        
+        // Iterate over regions needing repainting
+        wxRegionIterator regions(GetUpdateRegion());
+        wxRect rect;
+        while (regions) {
+            rect = regions.GetRect();
+            dc.Blit(rect.x, rect.y, rect.width, rect.height, &memDC, rect.x, rect.y);
+            ++regions;
+        }
+    }
+
+    void AGGWindow::onEraseBackground(wxEraseEvent& WXUNUSED(event)) {
+	    // Do nothing to "avoid flashing in MSW"  Grr.
+    }
+
+}
+
diff --git a/assdraw/src/wxAGG/AGGWindow.h b/assdraw/src/wxAGG/AGGWindow.h
new file mode 100644
index 000000000..01039da39
--- /dev/null
+++ b/assdraw/src/wxAGG/AGGWindow.h
@@ -0,0 +1,68 @@
+#ifndef WX_AGG_WINDOW_H
+#define WX_AGG_WINDOW_H
+
+#include "PixelFormatConvertor.h"
+
+#include <wx/bitmap.h>
+#include <wx/rawbmp.h>
+#include <wx/window.h>
+#include <wx/dcmemory.h>
+
+#include "agg_rendering_buffer.h"
+
+namespace GUI {
+    
+    /// A simple widget that displays a bitmap that AGG can draw on.
+    /// It reallocates the bitmap so that it always is the current size of the 
+    /// entire panel and calls the virtual method draw() to draw to the bitmap.
+    /// This should be useable anywhere a wxWindow can be, e.g. in actual windows, 
+    /// buttons, etc.
+    class AGGWindow: public wxWindow {
+        public:
+        /// Create an AGGWindow.  Defaults are taken from wxWindow::wxWindow(), see 
+        /// that documentation for more information.
+        AGGWindow(wxWindow* parent, wxWindowID id = wxID_ANY, 
+                  const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                  long style = wxTAB_TRAVERSAL);
+        
+        /// Clean up resources held
+        virtual ~AGGWindow();
+        
+        protected:
+           
+        /// The conversion between wxWidgets' pixel format and AGG's pixel format
+        typedef PixelFormatConvertor<wxNativePixelFormat> PixelFormat;
+
+        /// The wxWidgets "pixel data" type, an accessor to the raw pixels
+        typedef wxPixelData<wxBitmap, PixelFormat::wxWidgetsType> PixelData;
+
+        
+        /// Create the bitmap given the current size.
+        void init(const int width, const int height);
+
+        /// Attach the AGG rendering buffer to the bitmap and call the user draw() code.
+        void attachAndDraw();
+    
+        /// Paint the bitmap onto the panel.
+        void onPaint(wxPaintEvent& event);
+        
+        /// Resize the bitmap to match the window.
+        void onSize(wxSizeEvent& event);
+
+        /// Handle the erase-background event.
+        void onEraseBackground(wxEraseEvent& event);
+        
+        /// Draw into the bitmap using AGG.
+        virtual void draw() = 0;
+
+        
+        wxBitmap* bitmap;               ///< wxWidgets bitmap for AGG to draw into
+        wxMemoryDC memDC;               ///< Memory "device context" for drawing the bitmap
+        
+        agg::rendering_buffer rBuf;     ///< AGG's rendering buffer, pointing into the bitmap
+    
+        DECLARE_EVENT_TABLE()           /// Allocate wxWidgets storage for event handlers
+    };
+}
+    
+#endif
diff --git a/assdraw/src/wxAGG/PixelFormatConvertor.h b/assdraw/src/wxAGG/PixelFormatConvertor.h
new file mode 100644
index 000000000..d1b0741c4
--- /dev/null
+++ b/assdraw/src/wxAGG/PixelFormatConvertor.h
@@ -0,0 +1,117 @@
+/*
+* Copyright (c) 2007, ai-chan
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the ASSDraw3 Team nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef WX_AGG_PIXEL_FORMAT_CONVERTOR_H
+#define WX_AGG_PIXEL_FORMAT_CONVERTOR_H
+
+#include "agg_pixfmt_rgb.h"
+#include "agg_pixfmt_rgba.h"
+
+namespace {
+
+    /// Given a particular combination of channel type, bits per pixel and 
+    /// channel indices, return the AGG format that matches.
+    /// The actual template specializations that follow give the actual types, 
+    /// and using a combination of parameters that are not listed will give 
+    /// a compile-time error.
+    template <typename Channel, int bitsPerPixel, int r, int g, int b, int a> 
+    struct wxWidgetsToAGGHelper {
+        //empty
+    };
+
+    /// 24-bit RGB 
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 24, 0, 1, 2, -1> {
+        typedef agg::pixfmt_rgb24 format;
+    };
+
+    /// 24-bit BGR
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 24, 2, 1, 0, -1> {
+        typedef agg::pixfmt_bgr24 format;
+    };
+
+    /// 32-bit RGB, alpha unused but stored as ARGB. 
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 32, 1, 2, 3, -1> {
+        typedef agg::pixfmt_argb32 format;
+    };
+
+    /// 32-bit RGB, alpha unused but stored as RGBA.
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 32, 0, 1, 2, -1> {
+        typedef agg::pixfmt_rgba32 format;
+    };
+
+    /// 32-bit BGR, alpha unused but stored as ABGR. 
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 32, 3, 2, 1, -1> {
+        typedef agg::pixfmt_abgr32 format;
+    };
+
+    /// 32-bit BGR, alpha unused but stored as BGRA.
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 32, 2, 1, 0, -1> {
+        typedef agg::pixfmt_bgra32 format;
+    };
+
+    /// 32-bit RGBA
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 32, 0, 1, 2, 3> {
+        typedef agg::pixfmt_rgba32 format;
+    };
+
+    /// 32-bit BGRA
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 32, 2, 1, 0, 3> {
+        typedef agg::pixfmt_bgra32 format;
+    };
+
+    /// 32-bit ARGB
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 32, 1, 2, 3, 0> {
+        typedef agg::pixfmt_argb32 format;
+    };
+
+    /// 32-bit ABGR
+    template <> struct wxWidgetsToAGGHelper<unsigned char, 32, 3, 2, 1, 0> {
+        typedef agg::pixfmt_abgr32 format;
+    };
+}
+
+namespace GUI {
+    /// Convert between a wxWidgets pixel format class and an AGG pixel format class.
+    /// Usage examples: 
+    /// PixelFormatConvertor<wxNativePixelFormat>::AGGType or 
+    /// PixelFormatConvertor<wxAlphaPixelFormat>::AGGType.
+    template <typename wxWidgetsPixelFormat>
+    class PixelFormatConvertor {
+    public:
+        typedef wxWidgetsPixelFormat wxWidgetsType;
+
+        // Break out the wxWidgets parameters and feed to the helper class.
+        typedef typename wxWidgetsToAGGHelper<typename wxWidgetsPixelFormat::ChannelType, 
+                                              wxWidgetsPixelFormat::BitsPerPixel,
+                                              wxWidgetsPixelFormat::RED,
+                                              wxWidgetsPixelFormat::GREEN,
+                                              wxWidgetsPixelFormat::BLUE,
+                                              wxWidgetsPixelFormat::ALPHA>::format AGGType;
+    };
+}
+
+#endif
-- 
GitLab