diff --git a/aegilib/aegilib.vcproj b/aegilib/aegilib.vcproj index d1213ac3a..4285eff65 100644 --- a/aegilib/aegilib.vcproj +++ b/aegilib/aegilib.vcproj @@ -235,6 +235,10 @@ RelativePath=".\include\aegilib\utils.h" > + + @@ -344,6 +348,10 @@ RelativePath=".\src\utils.cpp" > + + @@ -43,13 +44,26 @@ using namespace Aegilib; -////////////// -// Extensions +/////// +// SSA +StringArray FormatSSA::GetReadExtensions() const +{ + StringArray final; + final.push_back(L".ssa"); + return final; +} +StringArray FormatSSA::GetWriteExtensions() const +{ + return GetReadExtensions(); +} + + +/////// +// ASS StringArray FormatASS::GetReadExtensions() const { StringArray final; final.push_back(L".ass"); - final.push_back(L".ssa"); return final; } StringArray FormatASS::GetWriteExtensions() const @@ -58,10 +72,24 @@ StringArray FormatASS::GetWriteExtensions() const } +//////// +// ASS2 +StringArray FormatASS2::GetReadExtensions() const +{ + StringArray final; + final.push_back(L".ass"); + return final; +} +StringArray FormatASS2::GetWriteExtensions() const +{ + return GetReadExtensions(); +} + + /////////////// // Constructor -FormatHandlerASS::FormatHandlerASS(Model &_model) -: model(_model) +FormatHandlerASS::FormatHandlerASS(Model &_model,int version) +: model(_model), formatVersion(version) { } @@ -296,7 +324,20 @@ void FormatHandlerASS::ProcessGroup(String cur,String &curGroup,int &version) { void FormatHandlerASS::WriteSection(TextFileWriter &writer,SectionPtr section) { // Write name - writer.WriteLineToFile(_T("[") + section->GetName() + _T("]")); + wxString name = section->GetName(); + writer.WriteLineToFile(_T("[") + name + _T("]")); + + // Write program and library credits + if (name == _T("Script Info")) { + wxString programName = GetHostApplicationName(); + wxString programURL = GetHostApplicationURL(); + wxString libVersion = GetLibraryVersionString(); + wxString libURL = GetLibraryURL(); + writer.WriteLineToFile(_T("; Script generated by ") + programName); + if (!programURL.IsEmpty()) writer.WriteLineToFile(_T("; ") + programURL); + writer.WriteLineToFile(_T("; With ") + libVersion); + if (programURL != libURL) writer.WriteLineToFile(_T("; ") + libURL); + } // Write properties size_t props = section->GetPropertyCount(); @@ -310,6 +351,6 @@ void FormatHandlerASS::WriteSection(TextFileWriter &writer,SectionPtr section) for (size_t i=0;iGetEntry(i); shared_ptr serial = dynamic_pointer_cast(entry); - writer.WriteLineToFile(serial->ToText()); + writer.WriteLineToFile(serial->ToText(formatVersion)); } } diff --git a/aegilib/src/formats/format_ass.h b/aegilib/src/formats/format_ass.h index f7cd072c7..b329d0cb8 100644 --- a/aegilib/src/formats/format_ass.h +++ b/aegilib/src/formats/format_ass.h @@ -46,36 +46,35 @@ namespace Aegilib { class Model; class TextFileWriter; + // Interface to serialize classes class SerializeText { public: virtual ~SerializeText(){} - virtual String ToText() const=0; + virtual String ToText(int param) const=0; }; // Advanced Substation Alpha format handler class FormatHandlerASS : public FormatHandler { private: Model &model; + int formatVersion; SectionEntryPtr MakeEntry(const String &data,SectionPtr section,int version); void ProcessGroup(String cur,String &curGroup,int &version); void WriteSection(TextFileWriter &writer,SectionPtr section); public: - FormatHandlerASS(Model &model); + FormatHandlerASS(Model &model,int version); ~FormatHandlerASS(); void Load(wxInputStream &file,const String encoding); void Save(wxOutputStream &file,const String encoding); }; - // Advanced Substation Alpha format - class FormatASS : public Format { + // Advanced Substation Alpha format base class + class FormatASSFamily : public Format { public: - String GetName() const { return L"Advanced Substation Alpha"; } - StringArray GetReadExtensions() const; - StringArray GetWriteExtensions() const; - FormatHandlerPtr GetHandler(Model &model) const { return FormatHandlerPtr(new FormatHandlerASS(model)); } + virtual ~FormatASSFamily() {} bool CanStoreText() const { return true; } bool CanUseTime() const { return true; } @@ -85,6 +84,33 @@ namespace Aegilib { bool HasActors() const { return true; } }; + // Substation Alpha + class FormatSSA : public FormatASSFamily { + public: + FormatHandlerPtr GetHandler(Model &model) const { return FormatHandlerPtr(new FormatHandlerASS(model,0)); } + String GetName() const { return L"Substation Alpha"; } + StringArray GetReadExtensions() const; + StringArray GetWriteExtensions() const; + }; + + // Advanced Substation Alpha + class FormatASS : public FormatASSFamily { + public: + FormatHandlerPtr GetHandler(Model &model) const { return FormatHandlerPtr(new FormatHandlerASS(model,1)); } + String GetName() const { return L"Advanced Substation Alpha"; } + StringArray GetReadExtensions() const; + StringArray GetWriteExtensions() const; + }; + + // Advanced Substation Alpha 2 + class FormatASS2 : public FormatASSFamily { + public: + FormatHandlerPtr GetHandler(Model &model) const { return FormatHandlerPtr(new FormatHandlerASS(model,2)); } + String GetName() const { return L"Advanced Substation Alpha 2"; } + StringArray GetReadExtensions() const; + StringArray GetWriteExtensions() const; + }; + // Dialogue class DialogueASS : public SectionEntryDialogue, public SerializeText { private: @@ -98,7 +124,7 @@ namespace Aegilib { bool isComment; bool Parse(String data,int version); - String ToText() const; + String ToText(int param) const; public: // Constructors @@ -161,9 +187,9 @@ namespace Aegilib { float shadow_w; bool Parse(String data,int version); - int AlignSSAtoASS(int ssaAlignment); - int AlignASStoSSA(int assAlignment); - String ToText() const; + int AlignSSAtoASS(int ssaAlignment) const; + int AlignASStoSSA(int assAlignment) const; + String ToText(int param) const; public: // Constructors diff --git a/aegilib/src/formats/format_ass_dialogue.cpp b/aegilib/src/formats/format_ass_dialogue.cpp index 3131da4d9..5da81829f 100644 --- a/aegilib/src/formats/format_ass_dialogue.cpp +++ b/aegilib/src/formats/format_ass_dialogue.cpp @@ -138,8 +138,33 @@ bool DialogueASS::Parse(wxString rawData, int version) ///////////// // Serialize -String DialogueASS::ToText() const +String DialogueASS::ToText(int version) const { - String final = L"Dialogue"; + // Prepare + wxString final = _T(""); + + // Write comment or dialogue + if (isComment) final = _T("Comment: "); + else final = _T("Dialogue: "); + + // Write layer or marked + if (version >= 1) final += wxString::Format(_T("%01i,"),layer); + else final += _T("Marked=0,"); + + // Write times, style and actor + final += start.GetString(2,1) + _T(",") + end.GetString(2,1) + _T(",") + style + _T(",") + actor + _T(","); + + // Write margins + if (version <= 1) final += wxString::Format(_T("%04i,%04i,%04i,"),margin[0],margin[1],margin[2]); + else final += wxString::Format(_T("%04i,%04i,%04i,%04i,"),margin[0],margin[1],margin[2],margin[3]); + + // Write effect and text + final += effect + _T(",") + text; + + // Make sure that final has no line breaks + final.Replace(_T("\n"),_T("")); + final.Replace(_T("\r"),_T("")); + + // Return final return final; } diff --git a/aegilib/src/formats/format_ass_style.cpp b/aegilib/src/formats/format_ass_style.cpp index 26016e728..9975dbcea 100644 --- a/aegilib/src/formats/format_ass_style.cpp +++ b/aegilib/src/formats/format_ass_style.cpp @@ -35,6 +35,7 @@ #include "format_ass.h" #include "tokenizer.h" +#include "utils.h" using namespace Aegilib; @@ -124,6 +125,7 @@ bool StyleASS::Parse(String data,int version) encoding = tkn.GetInt(); // Read relative to + relativeTo = 0; if (version == 2) relativeTo = tkn.GetInt(); // End @@ -139,7 +141,7 @@ bool StyleASS::Parse(String data,int version) //////////////////////////////// // Convert SSA alignment to ASS -int StyleASS::AlignSSAtoASS(int align) +int StyleASS::AlignSSAtoASS(int align) const { switch(align) { case 1: return 1; @@ -158,17 +160,69 @@ int StyleASS::AlignSSAtoASS(int align) //////////////////////////////// // Convert ASS alignment to SSA -int StyleASS::AlignASStoSSA(int assAlignment) +int StyleASS::AlignASStoSSA(int align) const { - // TODO - return assAlignment; + switch (align) { + case 1: return 1; + case 2: return 2; + case 3: return 3; + case 4: return 9; + case 5: return 10; + case 6: return 11; + case 7: return 5; + case 8: return 6; + case 9: return 7; + default: return 2; + } } ///////////// // Serialize -String StyleASS::ToText() const +String StyleASS::ToText(int version) const { - String final = L"Style"; + // Final string + wxString final; + + // Calculate colour offset + int cOff = 0; + if (version >= 1) cOff = 1; + + // Calculate alignment + int align = alignment; + if (version == 0) align = AlignASStoSSA(align); + + // Name, font, fontsize, colours, bold, italics + final = wxString::Format(_T("Style: %s,%s,%s,%s,%s,%s,%s,%i,%i,"), + name.c_str(), font.c_str(), PrettyFloatD(fontSize).c_str(), + colour[0].GetVBHex(true,true,false).c_str(), colour[1].GetVBHex(true,true,false).c_str(), + colour[2+cOff].GetVBHex(true,true,false).c_str(), colour[3+cOff].GetVBHex(true,true,false).c_str(), + (bold? -1 : 0), (italic ? -1 : 0)); + + // ASS-only + final += wxString::Format(_T("%i,%i,%s,%s,%s,%s,"), + (underline?-1:0),(strikeout?-1:0),PrettyFloatD(scalex).c_str(),PrettyFloatD(scaley).c_str(), + PrettyFloatD(spacing).c_str(),PrettyFloatD(angle).c_str()); + + + // Borderstyle, outline width, shadow width, alignment, first three margins + final += wxString::Format(_T("%i,%s,%s,%i,%i,%i,%i,"), + borderStyle,PrettyFloatD(outline_w).c_str(),PrettyFloatD(shadow_w).c_str(), + align,margin[0],margin[1],margin[2]); + + // Fourth margin for ASS2 only + if (version == 2) final += wxString::Format(_T("%i,"),margin[3]); + + // Alpha level for SSA only + // TODO: write something relevant? + if (version == 0) final += wxString::Format(_T("%i,"),0); + + // Encoding + final += wxString::Format(_T("%i"),encoding); + + // Relative-to for ASS2 only + if (version == 2) final += wxString::Format(_T(",%i"),relativeTo); + + // Done return final; } diff --git a/aegilib/src/text_file_writer.cpp b/aegilib/src/text_file_writer.cpp index 575881080..b80e9e02a 100644 --- a/aegilib/src/text_file_writer.cpp +++ b/aegilib/src/text_file_writer.cpp @@ -48,16 +48,7 @@ TextFileWriter::TextFileWriter(wxOutputStream &stream,String enc) { // Setup IsFirst = true; - - // Set encoding - encoding = enc; - if (encoding == _T("Local")) conv = shared_ptr (wxConvCurrent,NullDeleter()); - else { - if (encoding.IsEmpty()) encoding = _T("UTF-8"); - if (encoding == _T("US-ASCII")) encoding = _T("ISO-8859-1"); - conv = shared_ptr (new wxCSConv(encoding)); - IsUnicode = encoding.Left(3) == _T("UTF"); - } + SetEncoding(enc); } @@ -103,12 +94,20 @@ void TextFileWriter::WriteLineToFile(Aegilib::String line,bool addLineBreak) { //////////////// // Set encoding -void TextFileWriter::SetEncoding() { +void TextFileWriter::SetEncoding(String enc) { // Prepare Is16 = false; - // UTF-16 - if (encoding.Left(6) == _T("UTF-16")) { - Is16 = true; + // Set encoding + encoding = enc; + if (encoding == _T("Local")) conv = shared_ptr (wxConvCurrent,NullDeleter()); + else { + if (encoding.IsEmpty()) encoding = _T("UTF-8"); + if (encoding == _T("US-ASCII")) encoding = _T("ISO-8859-1"); + conv = shared_ptr (new wxCSConv(encoding)); + IsUnicode = encoding.Left(3) == _T("UTF"); + if (encoding.Left(6) == _T("UTF-16")) { + Is16 = true; + } } } diff --git a/aegilib/src/text_file_writer.h b/aegilib/src/text_file_writer.h index 8d24562ba..eebcfab7a 100644 --- a/aegilib/src/text_file_writer.h +++ b/aegilib/src/text_file_writer.h @@ -50,7 +50,7 @@ namespace Aegilib { bool IsFirst; bool IsUnicode; - void SetEncoding(); + void SetEncoding(String encoding); public: TextFileWriter(wxOutputStream &stream,String encoding=_T("")); diff --git a/aegilib/src/time.cpp b/aegilib/src/time.cpp index 53bb59ec5..a53602133 100644 --- a/aegilib/src/time.cpp +++ b/aegilib/src/time.cpp @@ -39,7 +39,7 @@ using namespace Aegilib; ////////////////////// // Generates a string -String Time::GetString(int ms_precision,int h_precision) +String Time::GetString(int ms_precision,int h_precision) const { // Enforce sanity ms_precision = Mid(0,ms_precision,3); diff --git a/aegilib/src/utils.cpp b/aegilib/src/utils.cpp index e6838508b..164c99796 100644 --- a/aegilib/src/utils.cpp +++ b/aegilib/src/utils.cpp @@ -47,3 +47,38 @@ int Aegilib::StringToInt(const String &str) str.ToLong(&temp); return (int) temp; } + + +//////////////// +// Pretty float +String Aegilib::PrettyFloat(String src) { + if (src.Contains(_T("."))) { + size_t len = src.Length(); + while (src.Right(1) == _T("0")) { + len--; + src.Truncate(len); + } + if (src.Right(1) == _T(".")) { + len--; + src.Truncate(len); + } + } + return src; +} + +String Aegilib::PrettyFloatF(float src) { return Aegilib::PrettyFloat(wxString::Format(_T("%f"),src)); } +String Aegilib::PrettyFloatD(double src) { return Aegilib::PrettyFloat(wxString::Format(_T("%f"),src)); } + + +/////////////////// +// Float to string +String Aegilib::FloatToString(double value) { + return PrettyFloat(wxString::Format(_T("%f"),value)); +} + + +///////////////// +// Int to string +String Aegilib::IntegerToString(int value) { + return wxString::Format(_T("%i"),value); +} diff --git a/aegilib/src/version.cpp b/aegilib/src/version.cpp new file mode 100644 index 000000000..aebaa5f3f --- /dev/null +++ b/aegilib/src/version.cpp @@ -0,0 +1,82 @@ +// Copyright (c) 2008, Rodrigo Braz Monteiro +// 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 Aegisub Group 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB/AEGILIB +// +// Website: http://www.aegisub.net +// Contact: mailto:amz@aegisub.net +// + + +#include "version.h" +#include "tr1.h" +using namespace Aegilib; + + +//////////////// +// Library data +String Aegilib::GetLibraryName() +{ + return _T("Aegilib"); +} +String Aegilib::GetLibraryVersionString() +{ + return _T("Aegilib v0.x - EXPERIMENTAL"); +} +String Aegilib::GetLibraryURL() +{ + return _T("http://www.aegisub.net"); +} + + +///////////////////////// +// Host application data +static shared_ptr hostName; +static shared_ptr hostURL; + +void Aegilib::SetHostApplicationName(const String name) +{ + if (!hostName) hostName = shared_ptr (new String()); + *hostName = name; +} +void Aegilib::SetHostApplicationURL(const String url) +{ + if (!hostURL) hostName = shared_ptr (new String()); + *hostURL = url; +} +String Aegilib::GetHostApplicationName() +{ + if (hostName) return *hostName; + return L"unknown application"; +} +String Aegilib::GetHostApplicationURL() +{ + if (hostURL) return *hostURL; + return L""; +} diff --git a/aegilib/test/src/main.cpp b/aegilib/test/src/main.cpp index 54bae5213..11518d6f3 100644 --- a/aegilib/test/src/main.cpp +++ b/aegilib/test/src/main.cpp @@ -48,6 +48,7 @@ int main () { try { // Set up the lib FormatManager::InitializeFormats(); + Aegilib::SetHostApplicationName(L"Aegilib test program"); // Subtitles model Model subs;