forked from mia/Aegisub
Added a delta coder specific for ASS dialogue entries that seems (from very simple tests) to work. Warning: code not for the faint of heart.
Originally committed to SVN as r2069.
This commit is contained in:
parent
072d747921
commit
8e8f4bf530
14 changed files with 669 additions and 76 deletions
|
@ -224,6 +224,10 @@
|
|||
RelativePath=".\include\aegilib\colour.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\aegilib\deltacoder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\exception.cpp"
|
||||
>
|
||||
|
@ -317,34 +321,6 @@
|
|||
RelativePath=".\include\aegilib\format.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_dialogue.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_dialogue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_plain.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_style.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_style.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\aegilib\format_handler.h"
|
||||
>
|
||||
|
@ -357,6 +333,46 @@
|
|||
RelativePath=".\include\aegilib\format_manager.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="ASS"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_dialogue.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_dialogue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_dialogue_delta.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_dialogue_delta.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_plain.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_style.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\formats\format_ass_style.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Actions"
|
||||
|
|
|
@ -89,11 +89,13 @@ namespace Gorgonsub {
|
|||
class ActionModify : public Action {
|
||||
private:
|
||||
shared_ptr<SectionEntry> entry;
|
||||
shared_ptr<void> delta;
|
||||
const String section;
|
||||
int lineNumber;
|
||||
|
||||
public:
|
||||
ActionModify(shared_ptr<SectionEntry> entry,int line,const String §ion);
|
||||
ActionModify(shared_ptr<void> delta,int line,const String §ion);
|
||||
virtual ~ActionModify() {}
|
||||
|
||||
ActionPtr GetAntiAction(const Model &model) const;
|
||||
|
|
|
@ -64,6 +64,9 @@ namespace Gorgonsub {
|
|||
public:
|
||||
~ActionList();
|
||||
|
||||
String GetName() const { return actionName; }
|
||||
String GetOwner() const { return owner; }
|
||||
|
||||
void AddAction(const ActionPtr action);
|
||||
void Finish();
|
||||
|
||||
|
|
54
aegilib/include/aegilib/deltacoder.h
Normal file
54
aegilib/include/aegilib/deltacoder.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
// 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/GORGONSUB
|
||||
//
|
||||
// Website: http://www.aegisub.net
|
||||
// Contact: mailto:amz@aegisub.net
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "tr1.h"
|
||||
|
||||
namespace Gorgonsub {
|
||||
|
||||
// Void pointer prototyle
|
||||
typedef shared_ptr<void> VoidPtr;
|
||||
|
||||
// Deltacoder interface
|
||||
class DeltaCoder {
|
||||
public:
|
||||
virtual ~DeltaCoder() {}
|
||||
virtual VoidPtr EncodeDelta(VoidPtr from,VoidPtr to) const = 0;
|
||||
virtual VoidPtr EncodeReverseDelta(VoidPtr delta,VoidPtr object) const = 0;
|
||||
virtual void ApplyDelta(VoidPtr delta,VoidPtr object) const = 0;
|
||||
};
|
||||
typedef shared_ptr<DeltaCoder> DeltaCoderPtr;
|
||||
|
||||
};
|
|
@ -52,6 +52,13 @@ namespace Gorgonsub {
|
|||
|
||||
String GetString(int ms_precision,int h_precision) const;
|
||||
void Parse(const String &data);
|
||||
|
||||
bool operator == (const Time &par) const { return ms == par.ms; }
|
||||
bool operator != (const Time &par) const { return ms != par.ms; }
|
||||
bool operator < (const Time &par) const { return ms < par.ms; }
|
||||
bool operator > (const Time &par) const { return ms > par.ms; }
|
||||
bool operator <= (const Time &par) const { return ms <= par.ms; }
|
||||
bool operator >= (const Time &par) const { return ms >= par.ms; }
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#pragma once
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <wx/wfstream.h>
|
||||
#include "actionlist.h"
|
||||
#include "section.h"
|
||||
|
@ -58,7 +57,7 @@ namespace Gorgonsub {
|
|||
friend class Action;
|
||||
|
||||
typedef std::list<ViewPtr> ViewList;
|
||||
typedef std::stack<ActionListPtr,std::list<ActionListPtr> > ActionStack;
|
||||
typedef std::list<ActionListPtr> ActionStack;
|
||||
typedef shared_ptr<Format> FormatPtr;
|
||||
|
||||
private:
|
||||
|
@ -71,6 +70,8 @@ namespace Gorgonsub {
|
|||
|
||||
void ProcessActionList(const ActionList &actionList,int type=0);
|
||||
|
||||
String GetUndoMessage(const String owner=L"") const;
|
||||
String GetRedoMessage(const String owner=L"") const;
|
||||
bool CanUndo(const String owner=L"") const;
|
||||
bool CanRedo(const String owner=L"") const;
|
||||
void Undo(const String owner=L"");
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#pragma once
|
||||
#include "gorgonstring.h"
|
||||
#include "tr1.h"
|
||||
#include "deltacoder.h"
|
||||
|
||||
namespace Gorgonsub {
|
||||
|
||||
|
@ -79,6 +80,8 @@ namespace Gorgonsub {
|
|||
virtual String GetDefaultGroup() const =0;
|
||||
virtual SectionEntryPtr Clone() const =0;
|
||||
|
||||
virtual DeltaCoderPtr GetDeltaCoder() const { return DeltaCoderPtr(); }
|
||||
|
||||
static const SectionEntryPlainPtr GetAsPlain(const SectionEntryPtr &ptr);
|
||||
static const SectionEntryDialoguePtr GetAsDialogue(const SectionEntryPtr &ptr);
|
||||
static const SectionEntryDialogueConstPtr GetAsDialogue(const SectionEntryConstPtr &ptr);
|
||||
|
|
|
@ -114,19 +114,36 @@ void ActionRemove::Execute(Model &model)
|
|||
|
||||
///////////////////////////// Modify line /////////////////////////////
|
||||
|
||||
///////////////
|
||||
// Constructor
|
||||
////////////////
|
||||
// Constructors
|
||||
ActionModify::ActionModify(shared_ptr<SectionEntry> data,int line,const String &sName)
|
||||
: entry(data), lineNumber(line), section(sName) {}
|
||||
|
||||
ActionModify::ActionModify(shared_ptr<void> _delta,int line,const String &sName)
|
||||
: delta(_delta), lineNumber(line), section(sName) {}
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Create anti-action for insert
|
||||
ActionPtr ActionModify::GetAntiAction(const Model &model) const
|
||||
{
|
||||
// Get section and original line
|
||||
SectionPtr sect = GetSection(model,section);
|
||||
SectionEntryPtr entry = sect->GetEntry(lineNumber);
|
||||
return ActionPtr(new ActionModify(entry,lineNumber,section));
|
||||
SectionEntryPtr oldEntry = sect->GetEntry(lineNumber);
|
||||
|
||||
// Try to get a delta
|
||||
DeltaCoderPtr deltaCoder = oldEntry->GetDeltaCoder();
|
||||
if (deltaCoder) {
|
||||
VoidPtr _delta;
|
||||
if (entry) _delta = deltaCoder->EncodeDelta(entry,oldEntry);
|
||||
else _delta = deltaCoder->EncodeReverseDelta(delta,oldEntry);
|
||||
return ActionPtr(new ActionModify(_delta,lineNumber,section));
|
||||
}
|
||||
|
||||
// Store the whole original line
|
||||
else {
|
||||
return ActionPtr(new ActionModify(oldEntry,lineNumber,section));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -140,5 +157,9 @@ void ActionModify::Execute(Model &model)
|
|||
SectionPtr sect = GetSection(model,sectionName);
|
||||
|
||||
// Modify the line
|
||||
sect->GetEntryRef(lineNumber) = entry;
|
||||
if (delta) {
|
||||
SectionEntryPtr &ref = sect->GetEntryRef(lineNumber);
|
||||
ref->GetDeltaCoder()->ApplyDelta(delta,ref);
|
||||
}
|
||||
else sect->GetEntryRef(lineNumber) = entry;
|
||||
}
|
||||
|
|
|
@ -97,12 +97,12 @@ bool DialogueASS::Parse(wxString rawData, int version)
|
|||
}
|
||||
|
||||
// Get times
|
||||
start.Parse(tkn.GetString());
|
||||
end.Parse(tkn.GetString());
|
||||
time[0].Parse(tkn.GetString());
|
||||
time[1].Parse(tkn.GetString());
|
||||
|
||||
// Get style and actor
|
||||
style = tkn.GetString(true);
|
||||
actor = tkn.GetString(true);
|
||||
text[1] = tkn.GetString(true);
|
||||
text[2] = tkn.GetString(true);
|
||||
|
||||
// Get margins
|
||||
for (int i=0;i<3;i++) margin[i] = tkn.GetInt();
|
||||
|
@ -124,10 +124,10 @@ bool DialogueASS::Parse(wxString rawData, int version)
|
|||
}
|
||||
|
||||
// Get effect
|
||||
effect = temp;
|
||||
text[3] = temp;
|
||||
|
||||
// Get text
|
||||
text = tkn.GetTheRest();
|
||||
text[0] = tkn.GetTheRest();
|
||||
}
|
||||
|
||||
catch (...) {
|
||||
|
@ -156,14 +156,14 @@ String DialogueASS::ToText(int version) const
|
|||
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(",");
|
||||
final += time[0].GetString(2,1) + _T(",") + time[1].GetString(2,1) + _T(",") + text[1] + _T(",") + text[2] + _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;
|
||||
final += text[3] + _T(",") + text[0];
|
||||
|
||||
// Return final
|
||||
return final;
|
||||
|
@ -177,7 +177,7 @@ String DialogueASS::ToText(int version) const
|
|||
if (!isComment) size++; // Comment->Dialogue
|
||||
if (version == 0) size += 8; // "Marked=0"
|
||||
else if (version == 2) size += 5; // Fourth margin
|
||||
size += style.Length() + actor.Length() + effect.Length() + text.Length();
|
||||
for (size_t i=0;i<4;i++) size += text[i].Length();
|
||||
|
||||
// Allocate string
|
||||
wxString final;
|
||||
|
@ -197,17 +197,16 @@ String DialogueASS::ToText(int version) const
|
|||
else WriteText(buffer,_T("Marked=0,"),9,pos);
|
||||
|
||||
// Write times
|
||||
wxString tempStr = start.GetString(2,1);
|
||||
WriteText(buffer,&tempStr[0],10,pos);
|
||||
WriteChar(buffer,_T(','),pos);
|
||||
tempStr = end.GetString(2,1);
|
||||
WriteText(buffer,&tempStr[0],10,pos);
|
||||
WriteChar(buffer,_T(','),pos);
|
||||
for (size_t i=0;i<2;i++) {
|
||||
wxString tempStr = time[i].GetString(2,1);
|
||||
WriteText(buffer,&tempStr[0],10,pos);
|
||||
WriteChar(buffer,_T(','),pos);
|
||||
}
|
||||
|
||||
// Write style and actor
|
||||
WriteText(buffer,&style[0],style.Length(),pos);
|
||||
WriteText(buffer,&text[1][0],text[1].Length(),pos);
|
||||
WriteChar(buffer,_T(','),pos);
|
||||
WriteText(buffer,&actor[0],actor.Length(),pos);
|
||||
WriteText(buffer,&text[2][0],text[2].Length(),pos);
|
||||
WriteChar(buffer,_T(','),pos);
|
||||
|
||||
// Write margins
|
||||
|
@ -219,9 +218,9 @@ String DialogueASS::ToText(int version) const
|
|||
}
|
||||
|
||||
// Write effect and text
|
||||
WriteText(buffer,&effect[0],effect.Length(),pos);
|
||||
WriteText(buffer,&text[3][0],text[3].Length(),pos);
|
||||
WriteChar(buffer,_T(','),pos);
|
||||
WriteText(buffer,&text[0],text.Length(),pos);
|
||||
WriteText(buffer,&text[0][0],text[0].Length(),pos);
|
||||
|
||||
// Write terminator
|
||||
WriteText(buffer,_T("\0"),1,pos);
|
||||
|
|
|
@ -36,18 +36,18 @@
|
|||
#pragma once
|
||||
#include "gorgonstring.h"
|
||||
#include "section_entry_dialogue.h"
|
||||
#include "format_ass_dialogue_delta.h"
|
||||
#include "serialize.h"
|
||||
|
||||
namespace Gorgonsub {
|
||||
|
||||
// Dialogue
|
||||
class DialogueASS : public SectionEntryDialogue, public SerializeText {
|
||||
friend class DialogueASSDeltaCoder;
|
||||
|
||||
private:
|
||||
String text;
|
||||
String style;
|
||||
String effect;
|
||||
String actor;
|
||||
Time start,end;
|
||||
array<Time,2> time;
|
||||
array<String,4> text; // 0 = text, 1 = style, 2 = actor, 3 = effect
|
||||
array<short,4> margin;
|
||||
int layer;
|
||||
bool isComment;
|
||||
|
@ -63,6 +63,7 @@ namespace Gorgonsub {
|
|||
// Basic features
|
||||
String GetDefaultGroup() const { return L"Events"; }
|
||||
SectionEntryPtr Clone() const { return SectionEntryPtr(new DialogueASS(*this)); }
|
||||
DeltaCoderPtr GetDeltaCoder() const { return DeltaCoderPtr(new DialogueASSDeltaCoder()); }
|
||||
|
||||
// Capabilities
|
||||
bool HasText() const { return true; }
|
||||
|
@ -71,25 +72,26 @@ namespace Gorgonsub {
|
|||
bool HasMargins() const { return true; }
|
||||
|
||||
// Read accessors
|
||||
const String& GetText() const { return text; }
|
||||
Time GetStartTime() const { return start; }
|
||||
Time GetEndTime() const { return end; }
|
||||
Time GetStartTime() const { return time[0]; }
|
||||
Time GetEndTime() const { return time[1]; }
|
||||
bool IsComment() const { return isComment; }
|
||||
int GetLayer() const { return layer; }
|
||||
int GetMargin(int n) const { return margin.at(n); }
|
||||
const String& GetStyle() const { return style; }
|
||||
const String& GetActor() const { return actor; }
|
||||
const String& GetUserField() const { return effect; }
|
||||
const String& GetText() const { return text[0]; }
|
||||
const String& GetStyle() const { return text[1]; }
|
||||
const String& GetActor() const { return text[2]; }
|
||||
const String& GetUserField() const { return text[3]; }
|
||||
|
||||
// Write acessors
|
||||
void SetText(const String &setText) { text = setText; }
|
||||
void SetStartTime(Time setStart) { start = setStart; }
|
||||
void SetEndTime(Time setEnd) { end = setEnd; }
|
||||
void SetStartTime(Time setStart) { time[0] = setStart; }
|
||||
void SetEndTime(Time setEnd) { time[1] = setEnd; }
|
||||
void SetComment(bool _isComment) { isComment = _isComment; }
|
||||
void SetLayer(int _layer) { layer = _layer; }
|
||||
void SetMargin(int _margin,int value) { margin.at(_margin) = value; }
|
||||
void SetStyle(const String &_style) { style = _style; }
|
||||
void SetUserField(const String &userField) { effect = userField; }
|
||||
void SetText(const String &setText) { text[0] = setText; }
|
||||
void SetStyle(const String &style) { text[1] = style; }
|
||||
void SetActor(const String &actor) { text[2] = actor; }
|
||||
void SetUserField(const String &userField) { text[3] = userField; }
|
||||
};
|
||||
|
||||
};
|
||||
|
|
195
aegilib/src/formats/format_ass_dialogue_delta.cpp
Normal file
195
aegilib/src/formats/format_ass_dialogue_delta.cpp
Normal file
|
@ -0,0 +1,195 @@
|
|||
// 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/GORGONSUB
|
||||
//
|
||||
// Website: http://www.aegisub.net
|
||||
// Contact: mailto:amz@aegisub.net
|
||||
//
|
||||
|
||||
#include "format_ass_dialogue_delta.h"
|
||||
#include "format_ass_dialogue.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "../stdint.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
using namespace Gorgonsub;
|
||||
|
||||
|
||||
////////////////////////////////////
|
||||
// Encode delta between two entries
|
||||
VoidPtr DialogueASSDeltaCoder::EncodeDelta(VoidPtr _from,VoidPtr _to) const
|
||||
{
|
||||
// Cast pointers
|
||||
shared_ptr<DialogueASS> from = static_pointer_cast<DialogueASS> (_from);
|
||||
shared_ptr<DialogueASS> to = static_pointer_cast<DialogueASS> (_to);
|
||||
|
||||
// Determine changes
|
||||
unsigned short mask = 0;
|
||||
if (from->isComment != to->isComment) mask |= 0x0001;
|
||||
if (from->layer != to->layer) mask |= 0x0002;
|
||||
if (from->time[0] != to->time[0]) mask |= 0x0004;
|
||||
if (from->time[1] != to->time[1]) mask |= 0x0008;
|
||||
for (size_t i=0;i<4;i++) {
|
||||
if (from->margin[i] != to->margin[i]) mask |= 0x0010 << i;
|
||||
if (from->text[i] != to->text[i]) mask |= 0x0100 << i;
|
||||
}
|
||||
|
||||
// Calculate final size and allocate
|
||||
size_t size = 2 + (mask & 0x0002)*4 + (mask & 0x0004)*4 + (mask & 0x0008)*4;
|
||||
for (size_t i=0;i<4;i++) {
|
||||
if (mask & (0x0010 << i)) size += 2;
|
||||
if (mask & (0x0100 << i)) size += (to->text[i].Length()+1)*2;
|
||||
}
|
||||
shared_ptr<std::vector<char> > delta (new std::vector<char>(size));
|
||||
|
||||
// Write data
|
||||
char *final = &delta->front();
|
||||
GetDelta(mask,final,to);
|
||||
|
||||
// Return delta
|
||||
return delta;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Calculates reverse delta
|
||||
VoidPtr DialogueASSDeltaCoder::EncodeReverseDelta(VoidPtr _delta,VoidPtr object) const
|
||||
{
|
||||
// Get mask
|
||||
char *data = &(static_pointer_cast<std::vector<char> > (_delta))->front();
|
||||
int mask = *((short*) data);
|
||||
shared_ptr<DialogueASS> to = static_pointer_cast<DialogueASS> (object);
|
||||
|
||||
// Calculate final size and allocate
|
||||
size_t size = 2 + (mask & 0x0002)*4 + (mask & 0x0004)*4 + (mask & 0x0008)*4;
|
||||
for (size_t i=0;i<4;i++) {
|
||||
size += (mask & (0x0010 << i)) * 2 + (mask & (0x0100 << i)) * (to->text[i].Length()+1)*2;
|
||||
}
|
||||
shared_ptr<std::vector<char> > delta (new std::vector<char>(size));
|
||||
|
||||
// Write data
|
||||
char *final = &delta->front();
|
||||
GetDelta(mask,final,to);
|
||||
return delta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// Applies delta to a line
|
||||
void DialogueASSDeltaCoder::ApplyDelta(VoidPtr _delta,VoidPtr object) const
|
||||
{
|
||||
// Process parameters
|
||||
char *data = &(static_pointer_cast<std::vector<char> > (_delta))->front();
|
||||
shared_ptr<DialogueASS> to = static_pointer_cast<DialogueASS> (object);
|
||||
|
||||
// Read mask
|
||||
int mask = *((int16_t*) data);
|
||||
data += 2;
|
||||
|
||||
// Toggle comment
|
||||
if (mask & 0x0001) to->isComment = !to->isComment;
|
||||
|
||||
// Read layer
|
||||
if (mask & 0x0002) {
|
||||
to->layer = *((int32_t*) data);
|
||||
data += 4;
|
||||
}
|
||||
|
||||
// Read times
|
||||
for (size_t i=0;i<2;i++) {
|
||||
if (mask & (0x0004 << i)) {
|
||||
to->time[i].SetMS(*((int32_t*) data));
|
||||
data += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Read margins
|
||||
for (size_t i=0;i<4;i++) {
|
||||
if (mask & (0x0010 << i)) {
|
||||
to->margin[i] = *((int16_t*) data);
|
||||
data += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Read text fields
|
||||
for (size_t i=0;i<4;i++) {
|
||||
if (mask & (0x0100 << i)) {
|
||||
to->text[i] = wxString((wchar_t*) data);
|
||||
data += (to->text[i].Length() + 1)*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// Actually get delta data
|
||||
void DialogueASSDeltaCoder::GetDelta(int mask,char *final,shared_ptr<DialogueASS> to) const
|
||||
{
|
||||
// Write mask
|
||||
*((uint16_t*) final) = mask;
|
||||
final += 2;
|
||||
|
||||
// Write layer
|
||||
if (mask & 0x0002) {
|
||||
*((int32_t*) final) = to->layer;
|
||||
final += 4;
|
||||
}
|
||||
|
||||
// Write times
|
||||
for (size_t i=0;i<2;i++) {
|
||||
if (mask & (0x0004 << i)) {
|
||||
*((int32_t*) final) = to->time[i].GetMS();
|
||||
final += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Write margins
|
||||
for (size_t i=0;i<4;i++) {
|
||||
if (mask & (0x0010 << i)) {
|
||||
*((int16_t*) final) = to->margin[i];
|
||||
final += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Write text fields
|
||||
for (size_t i=0;i<4;i++) {
|
||||
if (mask & (0x0100 << i)) {
|
||||
size_t len = (to->text[i].Length() + 1)*2;
|
||||
memcpy(final,to->text[i].c_str(),len);
|
||||
final += len-2;
|
||||
*(final++) = 0;
|
||||
*(final++) = 0;
|
||||
final += len;
|
||||
}
|
||||
}
|
||||
}
|
53
aegilib/src/formats/format_ass_dialogue_delta.h
Normal file
53
aegilib/src/formats/format_ass_dialogue_delta.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
// 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/GORGONSUB
|
||||
//
|
||||
// Website: http://www.aegisub.net
|
||||
// Contact: mailto:amz@aegisub.net
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "deltacoder.h"
|
||||
|
||||
namespace Gorgonsub {
|
||||
|
||||
// Delta coder
|
||||
class DialogueASS;
|
||||
class DialogueASSDeltaCoder : public DeltaCoder {
|
||||
private:
|
||||
void GetDelta(int mask,char *dst,shared_ptr<DialogueASS> to) const;
|
||||
|
||||
public:
|
||||
VoidPtr EncodeDelta(VoidPtr from,VoidPtr to) const;
|
||||
VoidPtr EncodeReverseDelta(VoidPtr from,VoidPtr to) const;
|
||||
void ApplyDelta(VoidPtr delta,VoidPtr object) const;
|
||||
};
|
||||
|
||||
};
|
|
@ -81,8 +81,8 @@ void Model::ProcessActionList(const ActionList &_actionList,int type)
|
|||
|
||||
// Insert into undo stack
|
||||
if (actions->undoAble) {
|
||||
stack->push(undo);
|
||||
if (type == 0) redoStack = ActionStack();
|
||||
stack->push_back(undo);
|
||||
if (type == 0) redoStack.clear();
|
||||
}
|
||||
|
||||
// Notify listeners
|
||||
|
@ -179,8 +179,8 @@ size_t Model::GetSectionCount() const
|
|||
void Model::Clear()
|
||||
{
|
||||
sections.clear();
|
||||
undoStack = ActionStack();
|
||||
redoStack = ActionStack();
|
||||
undoStack.clear();
|
||||
redoStack.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -222,8 +222,24 @@ void Model::ActivateStack(ActionStack &stack,bool isUndo,const String &owner)
|
|||
(void) owner;
|
||||
|
||||
// Process list
|
||||
ProcessActionList(*stack.top(),isUndo?1:2);
|
||||
ProcessActionList(*stack.back(),isUndo?1:2);
|
||||
|
||||
// Pop original
|
||||
stack.pop();
|
||||
stack.pop_back();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////
|
||||
// Get undo/redo messages
|
||||
String Model::GetUndoMessage(const String owner) const
|
||||
{
|
||||
(void) owner;
|
||||
if (CanUndo()) return undoStack.back()->GetName();
|
||||
return L"";
|
||||
}
|
||||
String Model::GetRedoMessage(const String owner) const
|
||||
{
|
||||
(void) owner;
|
||||
if (CanRedo()) return redoStack.back()->GetName();
|
||||
return L"";
|
||||
}
|
||||
|
|
221
aegilib/src/stdint.h
Normal file
221
aegilib/src/stdint.h
Normal file
|
@ -0,0 +1,221 @@
|
|||
// ISO C9x compliant stdint.h for Miscrosoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#if (_MSC_VER < 1300) && defined(__cplusplus)
|
||||
extern "C++" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#if (_MSC_VER < 1300) && defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN _I8_MIN
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN _I16_MIN
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN _I32_MIN
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN _I64_MIN
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val
|
||||
#define INT16_C(val) val
|
||||
#define INT32_C(val) val##L
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val
|
||||
#define UINT16_C(val) val
|
||||
#define UINT32_C(val) val##UL
|
||||
#define UINT64_C(val) val##Ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
#endif // _MSC_VER ]
|
Loading…
Reference in a new issue