From a0d3b8595fc8cd25dc733653fcbbc4172d5c4f63 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Mon, 10 Dec 2012 14:19:28 -0800 Subject: [PATCH] Redesign AssOverrideParameter Always store the original string form and convert it to the desired type on demand. In most cases this is significantly faster as typically only a few of the parameters in a line are actually read. In addition, this makes it so that parameters which did not actually change are always reserialized in their original form. Delete VariableData as it's no longer used by anything. Closes #1513. --- aegisub/build/Aegisub/Aegisub.vcxproj | 2 - aegisub/build/Aegisub/Aegisub.vcxproj.filters | 8 +- aegisub/src/Makefile | 1 - aegisub/src/ass_override.cpp | 146 ++++++++------ aegisub/src/ass_override.h | 31 ++- aegisub/src/subtitle_format_ebu3264.cpp | 2 +- aegisub/src/variable_data.cpp | 178 ------------------ aegisub/src/variable_data.h | 82 -------- aegisub/src/visual_tool.cpp | 18 +- 9 files changed, 123 insertions(+), 345 deletions(-) delete mode 100644 aegisub/src/variable_data.cpp delete mode 100644 aegisub/src/variable_data.h diff --git a/aegisub/build/Aegisub/Aegisub.vcxproj b/aegisub/build/Aegisub/Aegisub.vcxproj index e0a060076..35a522f99 100644 --- a/aegisub/build/Aegisub/Aegisub.vcxproj +++ b/aegisub/build/Aegisub/Aegisub.vcxproj @@ -232,7 +232,6 @@ - @@ -426,7 +425,6 @@ - diff --git a/aegisub/build/Aegisub/Aegisub.vcxproj.filters b/aegisub/build/Aegisub/Aegisub.vcxproj.filters index ef0128fb1..86e99171d 100644 --- a/aegisub/build/Aegisub/Aegisub.vcxproj.filters +++ b/aegisub/build/Aegisub/Aegisub.vcxproj.filters @@ -630,9 +630,6 @@ Utilities - - Utilities - Features\Help @@ -1179,9 +1176,6 @@ Utilities - - Utilities - Features\Help @@ -1245,4 +1239,4 @@ Resources - \ No newline at end of file + diff --git a/aegisub/src/Makefile b/aegisub/src/Makefile index fbc6c1da1..632a0c624 100644 --- a/aegisub/src/Makefile +++ b/aegisub/src/Makefile @@ -245,7 +245,6 @@ SRC += \ tooltip_manager.cpp \ utils.cpp \ validators.cpp \ - variable_data.cpp \ vector2d.cpp \ version.cpp \ video_box.cpp \ diff --git a/aegisub/src/ass_override.cpp b/aegisub/src/ass_override.cpp index 7621b5735..dfcda5916 100644 --- a/aegisub/src/ass_override.cpp +++ b/aegisub/src/ass_override.cpp @@ -39,6 +39,7 @@ #include "ass_dialogue.h" #include "ass_override.h" +#include "compat.h" #include "utils.h" #include @@ -50,6 +51,84 @@ using namespace boost::adaptors; +AssOverrideParameter::AssOverrideParameter(VariableDataType type, AssParameterClass classification) +: type(type) +, classification(classification) +{ +} + +AssOverrideParameter::AssOverrideParameter(AssOverrideParameter&& o) +: value(std::move(o.value)) +, block(std::move(o.block)) +, type(o.type) +, classification(o.classification) +{ +} + +AssOverrideParameter::~AssOverrideParameter() { +} + +template<> wxString AssOverrideParameter::Get() const { + if (omitted) throw agi::InternalError("AssOverrideParameter::Get() called on omitted parameter", 0); + if (block.get()) { + wxString str(block->GetText()); + str.Replace("{", ""); + str.Replace("}", ""); + return str; + } + return value; +} + +template<> int AssOverrideParameter::Get() const { + long v = 0; + Get().ToLong(&v); + return v; +} + +template<> double AssOverrideParameter::Get() const { + double v = 0; + Get().ToDouble(&v); + return v; +} + +template<> float AssOverrideParameter::Get() const { + return Get(); +} + +template<> bool AssOverrideParameter::Get() const { + return Get() != 0; +} + +template<> agi::Color AssOverrideParameter::Get() const { + return from_wx(Get()); +} + +template<> AssDialogueBlockOverride *AssOverrideParameter::Get() const { + if (!block.get()) { + block.reset(new AssDialogueBlockOverride(Get())); + block->ParseTags(); + } + return block.get(); +} + +template<> void AssOverrideParameter::Set(wxString new_value) { + omitted = false; + value = new_value; + block.reset(); +} + +template<> void AssOverrideParameter::Set(int new_value) { + Set(wxString::Format("%d", new_value)); +} + +template<> void AssOverrideParameter::Set(double new_value) { + Set(wxString::Format("%g", new_value)); +} + +template<> void AssOverrideParameter::Set(bool new_value) { + Set(new_value); +} + namespace { /// The parameter is absent unless the total number of parameters is the /// indicated number. Note that only arguments not at the end need to be marked @@ -324,75 +403,19 @@ void parse_parameters(AssOverrideTag *tag, const wxString &text, AssOverrideTagP unsigned curPar = 0; for (auto& curproto : proto_it->params) { // Create parameter - tag->Params.emplace_back(); + tag->Params.emplace_back(curproto.type, curproto.classification); AssOverrideParameter *newparam = &tag->Params.back(); - newparam->classification = curproto.classification; // Check if it's optional and not present if (!(curproto.optional & parsFlag) || curPar >= totalPars) continue; - wxString curtok = paramList[curPar++]; - - if (curtok.empty()) { - curPar++; - continue; - } - - wxChar firstChar = curtok[0]; - bool auto4 = (firstChar == '!' || firstChar == '$' || firstChar == '%') && curproto.type != VARDATA_BLOCK; - if (auto4) { - newparam->Set(curtok); - continue; - } - - switch (curproto.type) { - case VARDATA_INT: { - long temp; - curtok.ToLong(&temp); - newparam->Set(temp); - break; - } - case VARDATA_FLOAT: { - double temp; - curtok.ToDouble(&temp); - newparam->Set(temp); - break; - } - case VARDATA_TEXT: - newparam->Set(curtok); - break; - case VARDATA_BOOL: { - long temp; - curtok.ToLong(&temp); - newparam->Set(temp != 0); - break; - } - case VARDATA_BLOCK: { - AssDialogueBlockOverride *temp = new AssDialogueBlockOverride(curtok); - temp->ParseTags(); - newparam->Set(temp); - break; - } - default: - break; - } + tag->Params.back().Set(paramList[curPar++]); } } } -AssOverrideParameter::AssOverrideParameter() -: classification(PARCLASS_NORMAL) -{ -} - -AssOverrideParameter::AssOverrideParameter(AssOverrideParameter&& o) -: VariableData(std::move(o)) -, classification(o.classification) -{ -} - // From ass_dialogue.h AssDialogueBlockOverride::~AssDialogueBlockOverride() { delete_clear(Tags); @@ -409,9 +432,8 @@ void AssDialogueBlockOverride::ParseTags() { curTag += tkn.GetNextToken(); // Check for parenthesis matching for \t - while (curTag.Freq('(') > curTag.Freq(')') && tkn.HasMoreTokens()) { + while (curTag.Freq('(') > curTag.Freq(')') && tkn.HasMoreTokens()) curTag << "\\" << tkn.GetNextToken(); - } Tags.push_back(new AssOverrideTag(curTag)); @@ -431,7 +453,7 @@ wxString AssDialogueBlockOverride::GetText() { void AssDialogueBlockOverride::ProcessParameters(ProcessParametersCallback callback, void *userData) { for (auto tag : Tags) { for (auto& par : tag->Params) { - if (par.GetType() == VARDATA_NONE) continue; + if (par.omitted) continue; callback(tag->Name, &par, userData); @@ -478,7 +500,7 @@ AssOverrideTag::operator wxString() const { // Add parameters result += join(Params - | filtered([](AssOverrideParameter const& p) { return p.GetType() != VARDATA_NONE; }) + | filtered([](AssOverrideParameter const& p) { return !p.omitted; } ) | transformed(param_str), wxS(",")); diff --git a/aegisub/src/ass_override.h b/aegisub/src/ass_override.h index feccb11b7..faad0f76b 100644 --- a/aegisub/src/ass_override.h +++ b/aegisub/src/ass_override.h @@ -32,9 +32,12 @@ /// @ingroup subs_storage /// +#include +#include #include -#include "variable_data.h" +class AssDialogueBlockOverride; +class wxString; /// Type of parameter; probably only used by the resample tool enum AssParameterClass { @@ -50,15 +53,37 @@ enum AssParameterClass { PARCLASS_DRAWING }; +enum VariableDataType { + VARDATA_INT, + VARDATA_FLOAT, + VARDATA_TEXT, + VARDATA_BOOL, + VARDATA_BLOCK +}; + /// A single parameter to an override tag -class AssOverrideParameter : public VariableData { +class AssOverrideParameter : boost::noncopyable { + wxString value; + mutable std::unique_ptr block; + VariableDataType type; + public: + AssOverrideParameter(VariableDataType type, AssParameterClass classification); AssOverrideParameter(AssOverrideParameter&&); + ~AssOverrideParameter(); /// Type of parameter AssParameterClass classification; - AssOverrideParameter(); + /// Is this parameter actually present? + bool omitted; + + VariableDataType GetType() const { return type; } + template void Set(T param); + template T Get() const; + template T Get(T def) const { + return !omitted ? Get() : def; + } }; class AssOverrideTag : boost::noncopyable { diff --git a/aegisub/src/subtitle_format_ebu3264.cpp b/aegisub/src/subtitle_format_ebu3264.cpp index 8065625d8..d63565118 100644 --- a/aegisub/src/subtitle_format_ebu3264.cpp +++ b/aegisub/src/subtitle_format_ebu3264.cpp @@ -130,7 +130,7 @@ namespace italic = t->Params[0].Get(style_italic); else if (t->Name == "\\an") align = t->Params[0].Get(align); - else if (t->Name == "\\a" && t->Params[0].GetType() != VARDATA_NONE) + else if (t->Name == "\\a" && !t->Params[0].omitted) align = AssStyle::SsaToAss(t->Params[0].Get()); } } diff --git a/aegisub/src/variable_data.cpp b/aegisub/src/variable_data.cpp deleted file mode 100644 index eb125685e..000000000 --- a/aegisub/src/variable_data.cpp +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) 2005, 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 Project http://www.aegisub.org/ - -/// @file variable_data.cpp -/// @brief A variant-type implementation -/// @ingroup utility subs_storage - -#include "config.h" - -#include "variable_data.h" - -#include "ass_dialogue.h" -#include "ass_style.h" -#include "compat.h" -#include "utils.h" - -#include - -VariableData::VariableData() { - type = VARDATA_NONE; - value = nullptr; -} - -VariableData::VariableData(VariableData&& o) -: value(o.value) -, type(o.type) -{ -} - -VariableData::~VariableData() { - DeleteValue(); -} - -void VariableData::DeleteValue() { - if (!value) return; - if (type == VARDATA_NONE) return; - switch (type) { - case VARDATA_INT: delete value_int; break; - case VARDATA_FLOAT: delete value_float; break; - case VARDATA_TEXT: delete value_text; break; - case VARDATA_BOOL: delete value_bool; break; - case VARDATA_COLOUR: delete value_colour; break; - case VARDATA_BLOCK: delete *value_block; delete value_block; break; - default: break; - } - type = VARDATA_NONE; - value = nullptr; -} - -template static inline VariableDataType get_type(); - -template<> inline VariableDataType get_type() { - return VARDATA_INT; -} -template<> inline VariableDataType get_type() { - return VARDATA_FLOAT; -} -template<> inline VariableDataType get_type() { - return VARDATA_FLOAT; -} -template<> inline VariableDataType get_type() { - return VARDATA_BOOL; -} -template<> inline VariableDataType get_type() { - return VARDATA_TEXT; -} -template<> inline VariableDataType get_type() { - return VARDATA_COLOUR; -} -template<> inline VariableDataType get_type() { - return VARDATA_BLOCK; -} - -template -void VariableData::Set(T param) { - DeleteValue(); - type = get_type(); - value = new T(param); -} -template void VariableData::Set(int param); -template void VariableData::Set(float param); -template void VariableData::Set(double param); -template void VariableData::Set(bool param); -template void VariableData::Set(wxString param); -template void VariableData::Set(agi::Color param); -template void VariableData::Set(AssDialogueBlockOverride * param); - -template<> int VariableData::Get() const { - if (!value) throw "Null parameter"; - if (type == VARDATA_BOOL) return !!(*value_bool); - if (type == VARDATA_INT) return *value_int; - if (type == VARDATA_FLOAT) return (int)(*value_float); - if (type == VARDATA_TEXT) return 0; - throw "Wrong parameter type, should be int"; -} - -template<> float VariableData::Get() const { - if (!value) throw "Null parameter"; - if (type == VARDATA_FLOAT) return (float)*value_float; - if (type == VARDATA_INT) return (float)(*value_int); - if (type == VARDATA_TEXT) return 0.0f; - throw "Wrong parameter type, should be float"; -} -template<> double VariableData::Get() const { - if (!value) throw "Null parameter"; - if (type == VARDATA_FLOAT) return *value_float; - if (type == VARDATA_INT) return (float)(*value_int); - if (type == VARDATA_TEXT) return 0.0; - throw "Wrong parameter type, should be float"; -} - -template<> bool VariableData::Get() const { - if (!value) throw "Null parameter"; - if (type == VARDATA_BOOL) return *value_bool; - if (type == VARDATA_INT) return ((*value_int)!=0); - if (type == VARDATA_FLOAT) return ((*value_float)!=0); - if (type == VARDATA_TEXT) return false; - throw "Wrong parameter type, should be bool"; -} - -template<> agi::Color VariableData::Get() const { - if (!value) throw "Null parameter"; - if (type == VARDATA_COLOUR) return *value_colour; - else if (type == VARDATA_TEXT) { - return agi::Color(from_wx(*value_text)); - } - else throw "Wrong parameter type, should be colour"; -} - -template<> AssDialogueBlockOverride *VariableData::Get() const { - if (!value) throw "Null parameter"; - if (type != VARDATA_BLOCK) throw "Wrong parameter type, should be block"; - return *value_block; -} - -template<> wxString VariableData::Get() const { - if (!value) throw "Null parameter"; - if (type != VARDATA_TEXT) { - if (type == VARDATA_INT) return wxString::Format("%i",*value_int); - if (type == VARDATA_FLOAT) return wxString::Format("%g",*value_float); - if (type == VARDATA_COLOUR) return to_wx(value_colour->GetHexFormatted()); - if (type == VARDATA_BOOL) return *value_bool ? "1" : "0"; - if (type == VARDATA_BLOCK) { - wxString str((*value_block)->GetText()); - str.Replace("{", ""); - str.Replace("}", ""); - return str; - } - throw "Wrong parameter type, should be text"; - } - return *value_text; -} diff --git a/aegisub/src/variable_data.h b/aegisub/src/variable_data.h deleted file mode 100644 index fcbc9d08f..000000000 --- a/aegisub/src/variable_data.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2005, 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 Project http://www.aegisub.org/ - -/// @file variable_data.h -/// @see variable_data.cpp -/// @ingroup utility subs_storage -/// - -#pragma once - -#include - -namespace agi { struct Color; } -class wxString; - -enum VariableDataType { - VARDATA_NONE, - VARDATA_INT, - VARDATA_FLOAT, - VARDATA_TEXT, - VARDATA_BOOL, - VARDATA_COLOUR, - VARDATA_BLOCK -}; - -class AssDialogueBlockOverride; - -class VariableData : private boost::noncopyable { -private: - union { - void *value; - int *value_int; - double *value_float; - bool *value_bool; - wxString *value_text; - agi::Color *value_colour; - AssDialogueBlockOverride **value_block; - }; - - VariableDataType type; - -protected: - void DeleteValue(); - -public: - VariableData(); - VariableData(VariableData&& o); - virtual ~VariableData(); - - VariableDataType GetType() const { return type; } - template void Set(T param); - template T Get() const; - template T Get(T def) const { - return value ? Get() : def; - } -}; diff --git a/aegisub/src/visual_tool.cpp b/aegisub/src/visual_tool.cpp index 388773ef2..2058f3362 100644 --- a/aegisub/src/visual_tool.cpp +++ b/aegisub/src/visual_tool.cpp @@ -373,7 +373,7 @@ static param_vec find_tag(boost::ptr_vector& blocks, wxString static Vector2D vec_or_bad(param_vec tag, size_t x_idx, size_t y_idx) { if (!tag || tag->size() <= x_idx || tag->size() <= y_idx || - (*tag)[x_idx].GetType() == VARDATA_NONE || (*tag)[y_idx].GetType() == VARDATA_NONE) + (*tag)[x_idx].omitted || (*tag)[y_idx].omitted) { return Vector2D(); } @@ -401,8 +401,8 @@ Vector2D VisualToolBase::GetLinePosition(AssDialogue *diag) { param_vec align_tag; int ovr_align = 0; - if ((align_tag = find_tag(blocks, "\\an")) && (*align_tag)[0].GetType() != VARDATA_NONE) - ovr_align = (*align_tag)[0].Get(); + if ((align_tag = find_tag(blocks, "\\an"))) + ovr_align = (*align_tag)[0].Get(ovr_align); else if ((align_tag = find_tag(blocks, "\\a"))) ovr_align = AssStyle::SsaToAss((*align_tag)[0].Get(2)); @@ -462,13 +462,13 @@ void VisualToolBase::GetLineRotation(AssDialogue *diag, float &rx, float &ry, fl boost::ptr_vector blocks(diag->ParseTags()); if (param_vec tag = find_tag(blocks, "\\frx")) - rx = tag->front().Get(rx); + rx = tag->front().Get(rx); if (param_vec tag = find_tag(blocks, "\\fry")) - ry = tag->front().Get(ry); + ry = tag->front().Get(ry); if (param_vec tag = find_tag(blocks, "\\frz")) - rz = tag->front().Get(rz); + rz = tag->front().Get(rz); else if ((tag = find_tag(blocks, "\\fr"))) - rz = tag->front().Get(rz); + rz = tag->front().Get(rz); } void VisualToolBase::GetLineScale(AssDialogue *diag, Vector2D &scale) { @@ -482,9 +482,9 @@ void VisualToolBase::GetLineScale(AssDialogue *diag, Vector2D &scale) { boost::ptr_vector blocks(diag->ParseTags()); if (param_vec tag = find_tag(blocks, "\\fscx")) - x = tag->front().Get(x); + x = tag->front().Get(x); if (param_vec tag = find_tag(blocks, "\\fscy")) - y = tag->front().Get(y); + y = tag->front().Get(y); scale = Vector2D(x, y); }