forked from mia/Aegisub
Subs library should now be able to fully parse ASS files, except for file attachments. It's also missing any way of parsing override tags, and the interface accessors are incomplete.
Originally committed to SVN as r2031.
This commit is contained in:
parent
f5746ee0fc
commit
d70d4407e7
11 changed files with 242 additions and 48 deletions
|
@ -227,6 +227,10 @@
|
||||||
RelativePath=".\include\aegilib\tokenizer.h"
|
RelativePath=".\include\aegilib\tokenizer.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\include\aegilib\utils.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\include\aegilib\view.h"
|
RelativePath=".\include\aegilib\view.h"
|
||||||
>
|
>
|
||||||
|
@ -324,6 +328,10 @@
|
||||||
RelativePath=".\src\tokenizer.cpp"
|
RelativePath=".\src\tokenizer.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\utils.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Formats"
|
Name="Formats"
|
||||||
|
|
|
@ -49,16 +49,4 @@
|
||||||
#include "section_entry_style.h"
|
#include "section_entry_style.h"
|
||||||
#include "aegitime.h"
|
#include "aegitime.h"
|
||||||
#include "colour.h"
|
#include "colour.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
//////////
|
|
||||||
// Macros
|
|
||||||
#ifndef MAX
|
|
||||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
#ifndef MID
|
|
||||||
#define MID(a,b,c) MIN(MAX((a),(b)),(c))
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "aegistring.h"
|
#include "aegistring.h"
|
||||||
#include "section_entry.h"
|
#include "section_entry.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace Aegilib {
|
namespace Aegilib {
|
||||||
|
|
||||||
|
@ -44,14 +45,22 @@ namespace Aegilib {
|
||||||
class Section {
|
class Section {
|
||||||
private:
|
private:
|
||||||
std::list<SectionEntry*> entries;
|
std::list<SectionEntry*> entries;
|
||||||
|
std::map<String,String> properties;
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Section(String name);
|
Section(String name);
|
||||||
~Section();
|
~Section();
|
||||||
|
|
||||||
String GetName() const { return name; }
|
const String& GetName() const { return name; }
|
||||||
String SetName(String newName) { name = newName; }
|
String SetName(const String& newName) { name = newName; }
|
||||||
|
|
||||||
|
void SetProperty(const String &key,const String &value);
|
||||||
|
void UnsetProperty(const String &key);
|
||||||
|
String GetProperty(const String &key) const;
|
||||||
|
bool HasProperty(const String &key) const;
|
||||||
|
size_t PropertyCount() const;
|
||||||
|
String GetPropertyName(size_t index) const;
|
||||||
|
|
||||||
void AddEntry(SectionEntry *entry);
|
void AddEntry(SectionEntry *entry);
|
||||||
};
|
};
|
||||||
|
|
75
aegilib/include/aegilib/utils.h
Normal file
75
aegilib/include/aegilib/utils.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "aegilib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/////////////
|
||||||
|
// Templates
|
||||||
|
|
||||||
|
// Returns the largest of two values
|
||||||
|
template <typename T>
|
||||||
|
T Max(T a,T b)
|
||||||
|
{
|
||||||
|
if (b < a) return a;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the smallest of two values
|
||||||
|
template <typename T>
|
||||||
|
T Min(T a,T b)
|
||||||
|
{
|
||||||
|
if (a < b) return a;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns b, but limiting it to the interval [a,c]
|
||||||
|
template <typename T>
|
||||||
|
T Mid(T a,T b,T c)
|
||||||
|
{
|
||||||
|
return Min(Max(a,b),c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
// Helper functions
|
||||||
|
namespace Aegilib {
|
||||||
|
|
||||||
|
// Convert a string to an integer
|
||||||
|
int StringToInt(const String &str);
|
||||||
|
|
||||||
|
};
|
|
@ -62,10 +62,10 @@ Colour::Colour (int red,int green,int blue,int alpha)
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// Set colour component
|
// Set colour component
|
||||||
void Colour::SetRed(int red) { r = (unsigned char) MID(0,red,255); }
|
void Colour::SetRed(int red) { r = (unsigned char) Mid(0,red,255); }
|
||||||
void Colour::SetGreen(int green) { g = (unsigned char) MID(0,green,255); }
|
void Colour::SetGreen(int green) { g = (unsigned char) Mid(0,green,255); }
|
||||||
void Colour::SetBlue(int blue) { b = (unsigned char) MID(0,blue,255); }
|
void Colour::SetBlue(int blue) { b = (unsigned char) Mid(0,blue,255); }
|
||||||
void Colour::SetAlpha(int alpha) { a = (unsigned char) MID(0,alpha,255); }
|
void Colour::SetAlpha(int alpha) { a = (unsigned char) Mid(0,alpha,255); }
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
|
|
|
@ -108,20 +108,29 @@ void FormatHandlerASS::Load(wxInputStream &file,const String encoding)
|
||||||
if (cur[0] == L'[') continue;
|
if (cur[0] == L'[') continue;
|
||||||
|
|
||||||
// Create and insert line
|
// Create and insert line
|
||||||
SectionEntry *entry = MakeEntry(cur,curGroup,version);
|
SectionEntry *entry = MakeEntry(cur,section,version);
|
||||||
if (entry) section->AddEntry(entry);
|
if (entry) section->AddEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
cout << "\nFinished reading file with version=" << version << ".\n\n";
|
cout << "\nFinished reading file with version=" << version << ".\n";
|
||||||
|
cout << "Dumping properties:\n";
|
||||||
|
section = model.GetSection(_T("Script Info"));
|
||||||
|
size_t n = section->PropertyCount();
|
||||||
|
for (size_t i=0;i<n;i++) {
|
||||||
|
wxString name = section->GetPropertyName(i);
|
||||||
|
cout << name.mb_str(wxConvUTF8) << "=" << section->GetProperty(name).mb_str(wxConvUTF8) << endl;
|
||||||
|
}
|
||||||
|
cout << "Done.\n" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// Create line
|
// Create line
|
||||||
SectionEntry *FormatHandlerASS::MakeEntry(String data,String group,int version)
|
SectionEntry *FormatHandlerASS::MakeEntry(const String &data,Section *section,int version)
|
||||||
{
|
{
|
||||||
// Variables
|
// Variables
|
||||||
|
const String group = section->GetName();
|
||||||
SectionEntry *final = NULL;
|
SectionEntry *final = NULL;
|
||||||
|
|
||||||
// Attachments
|
// Attachments
|
||||||
|
@ -143,8 +152,7 @@ SectionEntry *FormatHandlerASS::MakeEntry(String data,String group,int version)
|
||||||
|
|
||||||
// Format lines
|
// Format lines
|
||||||
else if (data.Left(7) == _T("Format:")) {
|
else if (data.Left(7) == _T("Format:")) {
|
||||||
// TODO
|
section->SetProperty(_T("Format"),data.Mid(7).Trim(true).Trim(false));
|
||||||
//entry = new AssEntry(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Garbage
|
// Garbage
|
||||||
|
@ -164,8 +172,7 @@ SectionEntry *FormatHandlerASS::MakeEntry(String data,String group,int version)
|
||||||
std::cout << out.mb_str(wxConvUTF8) << std::endl;
|
std::cout << out.mb_str(wxConvUTF8) << std::endl;
|
||||||
}
|
}
|
||||||
if (data.Left(7) == _T("Format:")) {
|
if (data.Left(7) == _T("Format:")) {
|
||||||
// TODO
|
section->SetProperty(_T("Format"),data.Mid(7).Trim(true).Trim(false));
|
||||||
//entry = new AssEntry(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +181,15 @@ SectionEntry *FormatHandlerASS::MakeEntry(String data,String group,int version)
|
||||||
// Discard comments
|
// Discard comments
|
||||||
if (data.Left(1) == _T(";")) return NULL;
|
if (data.Left(1) == _T(";")) return NULL;
|
||||||
|
|
||||||
// TODO
|
// Parse property
|
||||||
|
size_t pos = data.Find(_T(':'));
|
||||||
|
if (pos == wxNOT_FOUND) return NULL;
|
||||||
|
wxString key = data.Left(pos).Trim(true).Trim(false);
|
||||||
|
wxString value = data.Mid(pos+1).Trim(true).Trim(false);
|
||||||
|
|
||||||
|
// Insert property
|
||||||
|
section->SetProperty(key,value);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return entry
|
// Return entry
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace Aegilib {
|
||||||
// Advanced Substation Alpha format handler
|
// Advanced Substation Alpha format handler
|
||||||
class FormatHandlerASS : public FormatHandler {
|
class FormatHandlerASS : public FormatHandler {
|
||||||
private:
|
private:
|
||||||
SectionEntry *MakeEntry(String data,String group,int version);
|
SectionEntry *MakeEntry(const String &data,Section *section,int version);
|
||||||
void ProcessGroup(String cur,String &curGroup,int &version);
|
void ProcessGroup(String cur,String &curGroup,int &version);
|
||||||
Model &model;
|
Model &model;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include "format_ass.h"
|
#include "format_ass.h"
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
|
#include "utils.h"
|
||||||
using namespace Aegilib;
|
using namespace Aegilib;
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,9 +91,7 @@ bool DialogueASS::Parse(wxString rawData, int version)
|
||||||
// Not SSA, so read layer number
|
// Not SSA, so read layer number
|
||||||
else {
|
else {
|
||||||
if (version == 0) version = 1; // Only do it for SSA, not ASS2
|
if (version == 0) version = 1; // Only do it for SSA, not ASS2
|
||||||
long templ;
|
layer = StringToInt(temp);
|
||||||
temp.ToLong(&templ);
|
|
||||||
layer = templ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get times
|
// Get times
|
||||||
|
@ -105,29 +104,25 @@ bool DialogueASS::Parse(wxString rawData, int version)
|
||||||
|
|
||||||
// Get margins
|
// Get margins
|
||||||
for (int i=0;i<3;i++) margin[i] = tkn.GetInt();
|
for (int i=0;i<3;i++) margin[i] = tkn.GetInt();
|
||||||
|
margin[3] = margin[2];
|
||||||
|
|
||||||
|
// Read next string, which is either bottom margin or effect
|
||||||
|
temp = tkn.GetString(true);
|
||||||
|
|
||||||
// Get bottom margin
|
// Get bottom margin
|
||||||
if (version == 1) margin[3] = margin[2];
|
|
||||||
bool rollBack = false;
|
|
||||||
if (version == 2) {
|
if (version == 2) {
|
||||||
wxString oldTemp = temp;
|
if (temp.IsNumber()) {
|
||||||
temp = tkn.GetString().Trim(false).Trim(true);
|
// Got margin
|
||||||
if (!temp.IsNumber()) {
|
margin[3] = StringToInt(temp);
|
||||||
version = 1;
|
|
||||||
rollBack = true;
|
// Read effect
|
||||||
}
|
temp = tkn.GetString(true);
|
||||||
else {
|
|
||||||
long templ;
|
|
||||||
temp.ToLong(&templ);
|
|
||||||
margin[3] = templ;
|
|
||||||
}
|
}
|
||||||
|
else version = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get effect
|
// Get effect
|
||||||
if (!rollBack) temp = tkn.GetString();
|
|
||||||
effect = temp;
|
effect = temp;
|
||||||
effect.Trim(true);
|
|
||||||
effect.Trim(false);
|
|
||||||
|
|
||||||
// Get text
|
// Get text
|
||||||
text = rawData.Mid(pos+tkn.GetPosition());
|
text = rawData.Mid(pos+tkn.GetPosition());
|
||||||
|
|
|
@ -59,3 +59,58 @@ void Section::AddEntry(SectionEntry *entry)
|
||||||
{
|
{
|
||||||
entries.push_back(entry);
|
entries.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// Set a property
|
||||||
|
void Section::SetProperty(const String &key,const String &value)
|
||||||
|
{
|
||||||
|
properties[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Removes a property
|
||||||
|
void Section::UnsetProperty(const String &key)
|
||||||
|
{
|
||||||
|
std::map<String,String>::iterator iter = properties.find(key);
|
||||||
|
if (iter != properties.end()) properties.erase(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// Get a property's value
|
||||||
|
String Section::GetProperty(const String &key) const
|
||||||
|
{
|
||||||
|
std::map<String,String>::const_iterator iter = properties.find(key);
|
||||||
|
if (iter != properties.end()) return iter->second;
|
||||||
|
else return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// Checks if it has a property
|
||||||
|
bool Section::HasProperty(const String &key) const
|
||||||
|
{
|
||||||
|
return properties.find(key) != properties.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Get property count
|
||||||
|
size_t Section::PropertyCount() const
|
||||||
|
{
|
||||||
|
return properties.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
// Get name of a property by index
|
||||||
|
String Section::GetPropertyName(size_t index) const
|
||||||
|
{
|
||||||
|
std::map<String,String>::const_iterator iter=properties.begin();
|
||||||
|
for (size_t i=0 ; iter!=properties.end() ; iter++,i++) {
|
||||||
|
if (i == index) return iter->first;
|
||||||
|
}
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
|
@ -42,8 +42,8 @@ using namespace Aegilib;
|
||||||
String Time::GetString(int ms_precision,int h_precision)
|
String Time::GetString(int ms_precision,int h_precision)
|
||||||
{
|
{
|
||||||
// Enforce sanity
|
// Enforce sanity
|
||||||
ms_precision = MID(0,ms_precision,3);
|
ms_precision = Mid(0,ms_precision,3);
|
||||||
h_precision = MID(0,h_precision,2);
|
h_precision = Mid(0,h_precision,2);
|
||||||
|
|
||||||
// Generate values
|
// Generate values
|
||||||
int _ms = ms;
|
int _ms = ms;
|
||||||
|
|
49
aegilib/src/utils.cpp
Normal file
49
aegilib/src/utils.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// 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 "utils.h"
|
||||||
|
using namespace Aegilib;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
// Convert a string to an integer
|
||||||
|
int Aegilib::StringToInt(const String &str)
|
||||||
|
{
|
||||||
|
if (!str.IsNumber()) return 0;
|
||||||
|
long temp;
|
||||||
|
str.ToLong(&temp);
|
||||||
|
return (int) temp;
|
||||||
|
}
|
Loading…
Reference in a new issue