mirror of https://github.com/odrling/Aegisub
Rewrite the Resample Resolution dialog
Use more appropriate controls rather than a pile of text ctrls and some not-entirely-correct validation of the values. Split apart the dialog and the actual resampling logic. Originally committed to SVN as r6599.
This commit is contained in:
parent
6f167e9293
commit
1077b9b5c4
|
@ -191,6 +191,7 @@
|
||||||
#include <wx/txtstrm.h>
|
#include <wx/txtstrm.h>
|
||||||
#include <wx/utils.h>
|
#include <wx/utils.h>
|
||||||
#include <wx/validate.h>
|
#include <wx/validate.h>
|
||||||
|
#include <wx/valgen.h>
|
||||||
#include <wx/valnum.h>
|
#include <wx/valnum.h>
|
||||||
#include <wx/valtext.h>
|
#include <wx/valtext.h>
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
|
|
|
@ -53,12 +53,12 @@
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/tokenzr.h>
|
#include <wx/tokenzr.h>
|
||||||
#include <wx/validate.h>
|
#include <wx/validate.h>
|
||||||
|
#include <wx/valgen.h>
|
||||||
#include <wx/valnum.h>
|
#include <wx/valnum.h>
|
||||||
#include <wx/window.h>
|
#include <wx/window.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <wx/valgen.h>
|
|
||||||
|
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,9 @@ struct tool_resampleres : public Command {
|
||||||
|
|
||||||
void operator()(agi::Context *c) {
|
void operator()(agi::Context *c) {
|
||||||
c->videoController->Stop();
|
c->videoController->Stop();
|
||||||
DialogResample(c).ShowModal();
|
ResampleSettings settings;
|
||||||
|
if (DialogResample(c, settings).ShowModal() == wxID_OK)
|
||||||
|
ResampleResolution(c->ass, settings);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,16 @@
|
||||||
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
// Copyright (c) 2012, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
// All rights reserved.
|
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// modification, are permitted provided that the following conditions are met:
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
// this list of conditions and the following disclaimer.
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
// and/or other materials provided with the distribution.
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// may be used to endorse or promote products derived from this software
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 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/
|
|
||||||
//
|
//
|
||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
|
@ -36,335 +21,238 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "dialog_resample.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <wx/log.h>
|
#include <algorithm>
|
||||||
#include <wx/msgdlg.h>
|
#include <tr1/functional>
|
||||||
|
|
||||||
|
#include <wx/checkbox.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/spinctrl.h>
|
||||||
|
#include <wx/statbox.h>
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
|
#include <wx/valgen.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "ass_override.h"
|
#include "ass_override.h"
|
||||||
#include "ass_style.h"
|
#include "ass_style.h"
|
||||||
#include "dialog_resample.h"
|
|
||||||
#include "include/aegisub/context.h"
|
#include "include/aegisub/context.h"
|
||||||
#include "help_button.h"
|
#include "help_button.h"
|
||||||
#include "libresrc/libresrc.h"
|
#include "libresrc/libresrc.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "validators.h"
|
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
|
||||||
// IDs
|
|
||||||
enum {
|
enum {
|
||||||
BUTTON_DEST_FROM_VIDEO = 1520,
|
LEFT = 0,
|
||||||
CHECK_ANAMORPHIC,
|
RIGHT = 1,
|
||||||
CHECK_SYMMETRICAL,
|
TOP = 2,
|
||||||
TEXT_MARGIN_T,
|
BOTTOM = 3
|
||||||
TEXT_MARGIN_L,
|
|
||||||
TEXT_MARGIN_R,
|
|
||||||
TEXT_MARGIN_B
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DialogResample::DialogResample(agi::Context *c)
|
DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings)
|
||||||
: wxDialog(c->parent,-1,_("Resample Resolution"),wxDefaultPosition)
|
: wxDialog(c->parent, -1, _("Resample Resolution"))
|
||||||
, c(c)
|
, c(c)
|
||||||
{
|
{
|
||||||
// Set icon
|
|
||||||
SetIcon(BitmapToIcon(GETIMAGE(resample_toolbutton_24)));
|
SetIcon(BitmapToIcon(GETIMAGE(resample_toolbutton_24)));
|
||||||
|
|
||||||
// Margins
|
memset(&settings, 0, sizeof(settings));
|
||||||
MarginSymmetrical = NULL; // Do not remove this
|
c->ass->GetResolution(settings.script_x, settings.script_y);
|
||||||
wxSizer *MarginBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Margin offset"));
|
|
||||||
wxSizer *MarginSizer = new wxGridSizer(3,3,5,5);
|
|
||||||
MarginTop = new wxTextCtrl(this,TEXT_MARGIN_T,"0",wxDefaultPosition,wxSize(50,-1),0);
|
|
||||||
MarginLeft = new wxTextCtrl(this,TEXT_MARGIN_L,"0",wxDefaultPosition,wxSize(50,-1),0);
|
|
||||||
MarginSymmetrical = new wxCheckBox(this,CHECK_SYMMETRICAL,_("&Symmetrical"));
|
|
||||||
MarginRight = new wxTextCtrl(this,TEXT_MARGIN_R,"0",wxDefaultPosition,wxSize(50,-1),0);
|
|
||||||
MarginBottom = new wxTextCtrl(this,TEXT_MARGIN_B,"0",wxDefaultPosition,wxSize(50,-1),0);
|
|
||||||
MarginSizer->AddSpacer(1);
|
|
||||||
MarginSizer->Add(MarginTop,1,wxEXPAND);
|
|
||||||
MarginSizer->AddSpacer(1);
|
|
||||||
MarginSizer->Add(MarginLeft,1,wxEXPAND);
|
|
||||||
MarginSizer->Add(MarginSymmetrical,1,wxEXPAND);
|
|
||||||
MarginSizer->Add(MarginRight,1,wxEXPAND);
|
|
||||||
MarginSizer->AddSpacer(1);
|
|
||||||
MarginSizer->Add(MarginBottom,1,wxEXPAND);
|
|
||||||
MarginSizer->AddSpacer(1);
|
|
||||||
MarginBoxSizer->Add(MarginSizer,1,wxALIGN_CENTER|wxBOTTOM,5);
|
|
||||||
MarginSymmetrical->SetValue(true);
|
|
||||||
MarginRight->Enable(false);
|
|
||||||
MarginBottom->Enable(false);
|
|
||||||
|
|
||||||
// Resolution
|
|
||||||
wxSizer *ResBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Resolution"));
|
|
||||||
wxSizer *ResSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
int sw,sh;
|
|
||||||
c->ass->GetResolution(sw,sh);
|
|
||||||
ResX = new wxTextCtrl(this,-1,"",wxDefaultPosition,wxSize(50,-1),0,NumValidator(sw));
|
|
||||||
ResY = new wxTextCtrl(this,-1,"",wxDefaultPosition,wxSize(50,-1),0,NumValidator(sh));
|
|
||||||
wxStaticText *ResText = new wxStaticText(this,-1,_("x"));
|
|
||||||
wxButton *FromVideo = new wxButton(this,BUTTON_DEST_FROM_VIDEO,_("From &video"));
|
|
||||||
if (!c->videoController->IsLoaded()) FromVideo->Enable(false);
|
|
||||||
ResSizer->Add(ResX,1,wxRIGHT,5);
|
|
||||||
ResSizer->Add(ResText,0,wxALIGN_CENTER | wxRIGHT,5);
|
|
||||||
ResSizer->Add(ResY,1,wxRIGHT,5);
|
|
||||||
ResSizer->Add(FromVideo,1,0,0);
|
|
||||||
Anamorphic = new wxCheckBox(this,CHECK_ANAMORPHIC,_("&Change aspect ratio"));
|
|
||||||
ResBoxSizer->Add(ResSizer,1,wxEXPAND|wxBOTTOM,5);
|
|
||||||
ResBoxSizer->Add(Anamorphic,0,0,0);
|
|
||||||
|
|
||||||
// Button sizer
|
// Create all controls and set validators
|
||||||
wxStdDialogButtonSizer *ButtonSizer = new wxStdDialogButtonSizer();
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
ButtonSizer->AddButton(new wxButton(this,wxID_OK));
|
margin_ctrl[i] = new wxSpinCtrl(this, -1, "0", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, -9999, 9999, 0);
|
||||||
ButtonSizer->AddButton(new wxButton(this,wxID_CANCEL));
|
margin_ctrl[i]->SetValidator(wxGenericValidator(&settings.margin[i]));
|
||||||
ButtonSizer->AddButton(new HelpButton(this,"Resample resolution"));
|
}
|
||||||
ButtonSizer->Realize();
|
|
||||||
|
|
||||||
// Main sizer
|
symmetrical = new wxCheckBox(this, -1, _("&Symmetrical"));
|
||||||
wxSizer *MainSizer = new wxBoxSizer(wxVERTICAL);
|
symmetrical->SetValue(true);
|
||||||
MainSizer->Add(MarginBoxSizer,1,wxEXPAND|wxALL,5);
|
|
||||||
MainSizer->Add(ResBoxSizer,0,wxEXPAND|wxALL,5);
|
margin_ctrl[RIGHT]->Enable(false);
|
||||||
MainSizer->Add(ButtonSizer,0,wxEXPAND|wxRIGHT|wxLEFT|wxBOTTOM,5);
|
margin_ctrl[BOTTOM]->Enable(false);
|
||||||
MainSizer->SetSizeHints(this);
|
|
||||||
SetSizer(MainSizer);
|
res_x = new wxSpinCtrl(this, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||||
|
res_y = new wxSpinCtrl(this, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||||
|
|
||||||
|
res_x->SetValidator(wxGenericValidator(&settings.script_x));
|
||||||
|
res_y->SetValidator(wxGenericValidator(&settings.script_y));
|
||||||
|
|
||||||
|
wxButton *from_video = new wxButton(this, -1, _("From &video"));
|
||||||
|
from_video->Enable(c->videoController->IsLoaded());
|
||||||
|
|
||||||
|
wxCheckBox *change_ar = new wxCheckBox(this, -1, _("&Change aspect ratio"));
|
||||||
|
change_ar->SetValidator(wxGenericValidator(&settings.change_ar));
|
||||||
|
|
||||||
|
// Position the controls
|
||||||
|
wxSizer *margin_sizer = new wxGridSizer(3, 3, 5, 5);
|
||||||
|
margin_sizer->AddSpacer(1);
|
||||||
|
margin_sizer->Add(margin_ctrl[TOP], wxSizerFlags(1).Expand());
|
||||||
|
margin_sizer->AddSpacer(1);
|
||||||
|
margin_sizer->Add(margin_ctrl[LEFT], wxSizerFlags(1).Expand());
|
||||||
|
margin_sizer->Add(symmetrical, wxSizerFlags(1).Expand());
|
||||||
|
margin_sizer->Add(margin_ctrl[RIGHT], wxSizerFlags(1).Expand());
|
||||||
|
margin_sizer->AddSpacer(1);
|
||||||
|
margin_sizer->Add(margin_ctrl[BOTTOM], wxSizerFlags(1).Expand());
|
||||||
|
margin_sizer->AddSpacer(1);
|
||||||
|
|
||||||
|
wxSizer *margin_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Margin offset"));
|
||||||
|
margin_box->Add(margin_sizer, wxSizerFlags(1).Expand().Border(wxBOTTOM));
|
||||||
|
|
||||||
|
wxSizer *res_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
res_sizer->Add(res_x, wxSizerFlags(1).Border(wxRIGHT));
|
||||||
|
res_sizer->Add(new wxStaticText(this, -1, _("x")), wxSizerFlags().Center().Border(wxRIGHT));
|
||||||
|
res_sizer->Add(res_y, wxSizerFlags(1).Border(wxRIGHT));
|
||||||
|
res_sizer->Add(from_video, wxSizerFlags(1));
|
||||||
|
|
||||||
|
wxSizer *res_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Resolution"));
|
||||||
|
res_box->Add(res_sizer, wxSizerFlags(1).Expand().Border(wxBOTTOM));
|
||||||
|
res_box->Add(change_ar);
|
||||||
|
|
||||||
|
wxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
main_sizer->Add(margin_box, wxSizerFlags(1).Expand().Border());
|
||||||
|
main_sizer->Add(res_box, wxSizerFlags(0).Expand().Border());
|
||||||
|
main_sizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxHELP), wxSizerFlags().Expand().Border(wxALL & ~wxTOP));
|
||||||
|
SetSizerAndFit(main_sizer);
|
||||||
CenterOnParent();
|
CenterOnParent();
|
||||||
instance = this;
|
|
||||||
|
// Bind events
|
||||||
|
using std::tr1::bind;
|
||||||
|
Bind(wxEVT_COMMAND_BUTTON_CLICKED, bind(&HelpButton::OpenPage, "Resample resolution"), wxID_HELP);
|
||||||
|
from_video->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogResample::SetDestFromVideo, this);
|
||||||
|
symmetrical->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &DialogResample::OnSymmetrical, this);
|
||||||
|
margin_ctrl[LEFT]->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, bind(&DialogResample::OnMarginChange, this, margin_ctrl[LEFT], margin_ctrl[RIGHT]));
|
||||||
|
margin_ctrl[TOP]->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, bind(&DialogResample::OnMarginChange, this, margin_ctrl[TOP], margin_ctrl[BOTTOM]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogResample::SetDestFromVideo(wxCommandEvent &) {
|
||||||
///////////////
|
res_x->SetValue(c->videoController->GetWidth());
|
||||||
// Event table
|
res_y->SetValue(c->videoController->GetHeight());
|
||||||
BEGIN_EVENT_TABLE(DialogResample,wxDialog)
|
|
||||||
EVT_BUTTON(wxID_OK,DialogResample::OnResample)
|
|
||||||
EVT_BUTTON(BUTTON_DEST_FROM_VIDEO,DialogResample::OnGetDestRes)
|
|
||||||
EVT_CHECKBOX(CHECK_SYMMETRICAL,DialogResample::OnSymmetrical)
|
|
||||||
EVT_TEXT(TEXT_MARGIN_T,DialogResample::OnMarginChange)
|
|
||||||
EVT_TEXT(TEXT_MARGIN_L,DialogResample::OnMarginChange)
|
|
||||||
EVT_TEXT(TEXT_MARGIN_R,DialogResample::OnMarginChange)
|
|
||||||
EVT_TEXT(TEXT_MARGIN_B,DialogResample::OnMarginChange)
|
|
||||||
END_EVENT_TABLE()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Resample tags
|
|
||||||
/// @param name
|
|
||||||
/// @param n
|
|
||||||
/// @param curParam
|
|
||||||
/// @param _curDiag
|
|
||||||
///
|
|
||||||
void DialogResample::ResampleTags (wxString name,int n,AssOverrideParameter *curParam,void *_curDiag) {
|
|
||||||
instance->DoResampleTags(name,n,curParam,_curDiag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief DOCME
|
void DialogResample::OnSymmetrical(wxCommandEvent &) {
|
||||||
/// @param name
|
bool state = !symmetrical->IsChecked();
|
||||||
/// @param n
|
|
||||||
/// @param curParam
|
|
||||||
/// @param _curDiag
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
void DialogResample::DoResampleTags (wxString name,int n,AssOverrideParameter *curParam,void *) {
|
|
||||||
double resizer = 1.0;
|
|
||||||
bool isX = false;
|
|
||||||
bool isY = false;
|
|
||||||
|
|
||||||
switch (curParam->classification) {
|
margin_ctrl[RIGHT]->Enable(state);
|
||||||
case PARCLASS_ABSOLUTE_SIZE:
|
margin_ctrl[BOTTOM]->Enable(state);
|
||||||
resizer = r;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PARCLASS_ABSOLUTE_POS_X:
|
|
||||||
resizer = rx;
|
|
||||||
isX = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PARCLASS_ABSOLUTE_POS_Y:
|
if (!state) {
|
||||||
resizer = ry;
|
margin_ctrl[RIGHT]->SetValue(margin_ctrl[LEFT]->GetValue());
|
||||||
isY = true;
|
margin_ctrl[BOTTOM]->SetValue(margin_ctrl[TOP]->GetValue());
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case PARCLASS_RELATIVE_SIZE_X:
|
void DialogResample::OnMarginChange(wxSpinCtrl *src, wxSpinCtrl *dst) {
|
||||||
resizer = ar;
|
if (symmetrical->IsChecked())
|
||||||
break;
|
dst->SetValue(src->GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
case PARCLASS_RELATIVE_SIZE_Y:
|
namespace {
|
||||||
//resizer = ry;
|
struct resample_state {
|
||||||
break;
|
const int *margin;
|
||||||
|
double rx;
|
||||||
|
double ry;
|
||||||
|
double ar;
|
||||||
|
};
|
||||||
|
|
||||||
case PARCLASS_DRAWING:
|
void resample_tags(wxString name, int n, AssOverrideParameter *cur, void *ud) {
|
||||||
{
|
resample_state *state = static_cast<resample_state *>(ud);
|
||||||
AssDialogueBlockDrawing block(curParam->Get<wxString>(), 1);
|
|
||||||
block.TransformCoords(m[0],m[2],rx,ry);
|
double resizer = 1.0;
|
||||||
curParam->Set(block.GetText());
|
int shift = 0;
|
||||||
|
|
||||||
|
switch (cur->classification) {
|
||||||
|
case PARCLASS_ABSOLUTE_SIZE:
|
||||||
|
resizer = state->ry;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARCLASS_ABSOLUTE_POS_X:
|
||||||
|
resizer = state->rx;
|
||||||
|
shift = state->margin[LEFT];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARCLASS_ABSOLUTE_POS_Y:
|
||||||
|
resizer = state->ry;
|
||||||
|
shift = state->margin[TOP];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARCLASS_RELATIVE_SIZE_X:
|
||||||
|
resizer = state->ar;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARCLASS_RELATIVE_SIZE_Y:
|
||||||
|
//resizer = ry;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARCLASS_DRAWING: {
|
||||||
|
AssDialogueBlockDrawing block(cur->Get<wxString>(), 1);
|
||||||
|
block.TransformCoords(state->margin[LEFT], state->margin[TOP], state->rx, state->ry);
|
||||||
|
cur->Set(block.GetText());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VariableDataType curType = cur->GetType();
|
||||||
|
if (curType == VARDATA_FLOAT)
|
||||||
|
cur->Set((cur->Get<double>() + shift) * resizer);
|
||||||
|
else if (curType == VARDATA_INT)
|
||||||
|
cur->Set<int>((cur->Get<int>() + shift) * resizer + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableDataType curType = curParam->GetType();
|
void resample_line(resample_state *state, AssEntry *line) {
|
||||||
if (curType == VARDATA_FLOAT) {
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(line);
|
||||||
float par = curParam->Get<double>();
|
if (diag && !(diag->Comment && (diag->Effect.StartsWith("template") || diag->Effect.StartsWith("code")))) {
|
||||||
if (isX) par += m[0];
|
diag->ParseASSTags();
|
||||||
if (isY) par += m[2];
|
diag->ProcessParameters(resample_tags, state);
|
||||||
curParam->Set<double>(par * resizer);
|
|
||||||
}
|
for (size_t i = 0; i < diag->Blocks.size(); ++i) {
|
||||||
if (curType == VARDATA_INT) {
|
if (AssDialogueBlockDrawing *block = dynamic_cast<AssDialogueBlockDrawing*>(diag->Blocks[i]))
|
||||||
int par = curParam->Get<int>();
|
block->TransformCoords(state->margin[LEFT], state->margin[TOP], state->rx, state->ry);
|
||||||
if (isX) par += m[0];
|
}
|
||||||
if (isY) par += m[2];
|
|
||||||
curParam->Set<int>(int(double(par) * resizer + 0.5));
|
for (size_t i = 0; i < 4; ++i)
|
||||||
|
diag->Margin[i] = int((diag->Margin[i] + state->margin[i]) * (i < 2 ? state->rx : state->ry) + 0.5);
|
||||||
|
|
||||||
|
|
||||||
|
diag->UpdateText();
|
||||||
|
diag->ClearBlocks();
|
||||||
|
}
|
||||||
|
else if (AssStyle *style = dynamic_cast<AssStyle*>(line)) {
|
||||||
|
style->fontsize = int(style->fontsize * state->ry + 0.5);
|
||||||
|
style->outline_w *= state->ry;
|
||||||
|
style->shadow_w *= state->ry;
|
||||||
|
style->spacing *= state->rx;
|
||||||
|
style->scalex *= state->ar;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
style->Margin[i] = int((style->Margin[i] + state->margin[i]) * (i < 2 ? state->rx : state->ry) + 0.5);
|
||||||
|
style->UpdateData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResampleResolution(AssFile *ass, ResampleSettings const& settings) {
|
||||||
|
int src_x, src_y;
|
||||||
/// @brief Resample
|
ass->GetResolution(src_x, src_y);
|
||||||
/// @param event
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
void DialogResample::OnResample (wxCommandEvent &) {
|
|
||||||
int x1,y1;
|
|
||||||
c->ass->GetResolution(x1,y1);
|
|
||||||
long x2 = 0;
|
|
||||||
long y2 = 0;
|
|
||||||
ResX->GetValue().ToLong(&x2);
|
|
||||||
ResY->GetValue().ToLong(&y2);
|
|
||||||
|
|
||||||
// Sanity check
|
|
||||||
if (x1 == 0 || y1 == 0) {
|
|
||||||
wxMessageBox("Invalid source resolution. This should not happen. Please contact the developers.",_("Error"),wxCENTRE|wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (x2 == 0 || y2 == 0) {
|
|
||||||
wxMessageBox(_("Invalid resolution: destination resolution cannot be 0 on either dimension."),_("Error"),wxCENTRE|wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get margins
|
|
||||||
MarginLeft->GetValue().ToLong(&m[0]);
|
|
||||||
MarginRight->GetValue().ToLong(&m[1]);
|
|
||||||
MarginTop->GetValue().ToLong(&m[2]);
|
|
||||||
MarginBottom->GetValue().ToLong(&m[3]);
|
|
||||||
|
|
||||||
// Add margins to original resolution
|
// Add margins to original resolution
|
||||||
x1 += m[0] + m[1];
|
src_x += settings.margin[LEFT] + settings.margin[RIGHT];
|
||||||
x2 += m[2] + m[3];
|
src_y += settings.margin[TOP] + settings.margin[BOTTOM];
|
||||||
|
|
||||||
// Calculate resamples
|
resample_state state = {
|
||||||
rx = double(x2)/double(x1);
|
settings.margin,
|
||||||
ry = double(y2)/double(y1);
|
double(settings.script_x) / double(src_x),
|
||||||
r = ry;
|
double(settings.script_y) / double(src_y),
|
||||||
if (Anamorphic->IsChecked()) ar = rx/ry;
|
settings.change_ar ? state.rx / state.ry : 1.0
|
||||||
else ar = 1.0;
|
};
|
||||||
|
|
||||||
// Iterate through subs
|
for_each(ass->Line.begin(), ass->Line.end(), bind(resample_line, &state, std::tr1::placeholders::_1));
|
||||||
AssStyle *curStyle;
|
|
||||||
AssDialogue *curDiag;
|
|
||||||
for (entryIter cur=c->ass->Line.begin();cur!=c->ass->Line.end();cur++) {
|
|
||||||
// Apply to dialogues
|
|
||||||
curDiag = dynamic_cast<AssDialogue*>(*cur);
|
|
||||||
if (curDiag && !(curDiag->Comment && (curDiag->Effect.StartsWith("template") || curDiag->Effect.StartsWith("code")))) {
|
|
||||||
try {
|
|
||||||
// Override tags
|
|
||||||
curDiag->ParseASSTags();
|
|
||||||
curDiag->ProcessParameters(&DialogResample::ResampleTags,curDiag);
|
|
||||||
|
|
||||||
// Drawing tags
|
ass->SetScriptInfo("PlayResX", wxString::Format("%d", settings.script_x));
|
||||||
size_t nblocks = curDiag->Blocks.size();
|
ass->SetScriptInfo("PlayResY", wxString::Format("%d", settings.script_y));
|
||||||
AssDialogueBlockDrawing *curBlock;
|
|
||||||
for (size_t i=0;i<nblocks;i++) {
|
|
||||||
curBlock = dynamic_cast<AssDialogueBlockDrawing*>(curDiag->Blocks.at(i));
|
|
||||||
if (curBlock) {
|
|
||||||
curBlock->TransformCoords(m[0],m[2],rx,ry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Margins
|
ass->Commit(_("resolution resampling"), AssFile::COMMIT_SCRIPTINFO | AssFile::COMMIT_DIAG_FULL);
|
||||||
for (int i=0;i<2;i++) {
|
|
||||||
curDiag->Margin[i] = int((curDiag->Margin[i]+m[i]) * rx + 0.5);
|
|
||||||
curDiag->Margin[i+2] = int((curDiag->Margin[i+2]+m[i+2]) * ry + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update
|
|
||||||
curDiag->UpdateText();
|
|
||||||
curDiag->ClearBlocks();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch (const char *err) {
|
|
||||||
wxLogMessage(err);
|
|
||||||
}
|
|
||||||
catch (wxString const& err) {
|
|
||||||
wxLogMessage(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply to styles
|
|
||||||
curStyle = dynamic_cast<AssStyle*>(*cur);
|
|
||||||
if (curStyle) {
|
|
||||||
curStyle->fontsize = int(curStyle->fontsize * r + 0.5);
|
|
||||||
curStyle->outline_w *= r;
|
|
||||||
curStyle->shadow_w *= r;
|
|
||||||
curStyle->spacing *= rx;
|
|
||||||
curStyle->scalex *= ar;
|
|
||||||
for (int i=0;i<2;i++) {
|
|
||||||
curStyle->Margin[i] = int((curStyle->Margin[i]+m[i]) * rx + 0.5);
|
|
||||||
curStyle->Margin[i+2] = int((curStyle->Margin[i+2]+m[i+2]) * ry + 0.5);
|
|
||||||
}
|
|
||||||
curStyle->UpdateData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change script resolution
|
|
||||||
c->ass->SetScriptInfo("PlayResX",wxString::Format("%i",x2));
|
|
||||||
c->ass->SetScriptInfo("PlayResY",wxString::Format("%i",y2));
|
|
||||||
|
|
||||||
// Flag as modified
|
|
||||||
c->ass->Commit(_("resolution resampling"), AssFile::COMMIT_SCRIPTINFO | AssFile::COMMIT_DIAG_FULL);
|
|
||||||
EndModal(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get destination resolution from video
|
|
||||||
/// @param event
|
|
||||||
///
|
|
||||||
void DialogResample::OnGetDestRes (wxCommandEvent &) {
|
|
||||||
ResX->SetValue(wxString::Format("%i",c->videoController->GetWidth()));
|
|
||||||
ResY->SetValue(wxString::Format("%i",c->videoController->GetHeight()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Symmetrical checkbox clicked
|
|
||||||
/// @param event
|
|
||||||
///
|
|
||||||
void DialogResample::OnSymmetrical (wxCommandEvent &) {
|
|
||||||
bool state = !MarginSymmetrical->IsChecked();
|
|
||||||
MarginRight->Enable(state);
|
|
||||||
MarginBottom->Enable(state);
|
|
||||||
if (!state) {
|
|
||||||
MarginRight->SetValue(MarginLeft->GetValue());
|
|
||||||
MarginBottom->SetValue(MarginTop->GetValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Margin value changed
|
|
||||||
/// @param event
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
void DialogResample::OnMarginChange (wxCommandEvent &event) {
|
|
||||||
if (!MarginSymmetrical) return;
|
|
||||||
bool state = !MarginSymmetrical->IsChecked();
|
|
||||||
if (!state && (event.GetEventObject() == MarginLeft || event.GetEventObject() == MarginTop)) {
|
|
||||||
MarginRight->SetValue(MarginLeft->GetValue());
|
|
||||||
MarginBottom->SetValue(MarginTop->GetValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
DialogResample *DialogResample::instance = NULL;
|
|
||||||
|
|
|
@ -1,31 +1,16 @@
|
||||||
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
// Copyright (c) 2012, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
// All rights reserved.
|
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// modification, are permitted provided that the following conditions are met:
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
// this list of conditions and the following disclaimer.
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
// and/or other materials provided with the distribution.
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// may be used to endorse or promote products derived from this software
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 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/
|
|
||||||
//
|
//
|
||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
|
@ -35,75 +20,53 @@
|
||||||
///
|
///
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <wx/checkbox.h>
|
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/string.h>
|
|
||||||
#include <wx/textctrl.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace agi { struct Context; }
|
namespace agi { struct Context; }
|
||||||
class AssOverrideParameter;
|
class AssFile;
|
||||||
|
class wxCheckBox;
|
||||||
|
class wxSpinCtrl;
|
||||||
|
|
||||||
|
/// Configuration parameters for a resample
|
||||||
|
struct ResampleSettings {
|
||||||
|
/// Amount to add to each margin
|
||||||
|
int margin[4];
|
||||||
|
/// New X resolution
|
||||||
|
int script_x;
|
||||||
|
/// New Y resolution
|
||||||
|
int script_y;
|
||||||
|
/// Should the aspect ratio of the subs be changed?
|
||||||
|
bool change_ar;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Resample the subtitles in the project
|
||||||
|
/// @param file Subtitles to resample
|
||||||
|
/// @param settings Resample configuration settings
|
||||||
|
void ResampleResolution(AssFile *file, ResampleSettings const& settings);
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class DialogResample
|
/// @class DialogResample
|
||||||
/// @brief DOCME
|
/// @brief Configuration dialog for resolution resampling
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// Populate a ResampleSettings structure with data from the user
|
||||||
class DialogResample : public wxDialog {
|
class DialogResample : public wxDialog {
|
||||||
agi::Context *c;
|
agi::Context *c; ///< Project context
|
||||||
|
|
||||||
/// DOCME
|
wxSpinCtrl *res_x;
|
||||||
wxTextCtrl *ResX;
|
wxSpinCtrl *res_y;
|
||||||
|
wxCheckBox *symmetrical;
|
||||||
|
wxSpinCtrl *margin_ctrl[4];
|
||||||
|
|
||||||
/// DOCME
|
/// Set the destination resolution to the video's resolution
|
||||||
wxTextCtrl *ResY;
|
void SetDestFromVideo(wxCommandEvent &);
|
||||||
|
/// Symmetrical checkbox toggle handler
|
||||||
/// DOCME
|
void OnSymmetrical(wxCommandEvent &);
|
||||||
wxTextCtrl *MarginLeft;
|
/// Copy margin values over if symmetrical is enabled
|
||||||
|
void OnMarginChange(wxSpinCtrl *src, wxSpinCtrl *dst);
|
||||||
/// DOCME
|
|
||||||
wxTextCtrl *MarginRight;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxTextCtrl *MarginTop;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxTextCtrl *MarginBottom;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxCheckBox *Anamorphic;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxCheckBox *MarginSymmetrical;
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
double rx,ry,r,ar;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
long m[4];
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
static DialogResample *instance;
|
|
||||||
|
|
||||||
void OnResample (wxCommandEvent &event);
|
|
||||||
void OnGetDestRes (wxCommandEvent &event);
|
|
||||||
void OnSymmetrical (wxCommandEvent &event);
|
|
||||||
void OnMarginChange (wxCommandEvent &event);
|
|
||||||
|
|
||||||
static void ResampleTags (wxString name,int n,AssOverrideParameter *curParam,void *_curDiag);
|
|
||||||
void DoResampleTags (wxString name,int n,AssOverrideParameter *curParam,void *_curDiag);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DialogResample(agi::Context *context);
|
/// Constructor
|
||||||
|
/// @param context Project context
|
||||||
DECLARE_EVENT_TABLE()
|
/// @param[out] settings Settings struct to populate
|
||||||
|
DialogResample(agi::Context *context, ResampleSettings &settings);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue