Fix #884, annoying wxString::Trim is destructive and there's no non-destructive variant. Adding a new function to utils.cpp to test whether a string is "blank", ie. empty or whitespace-only, as well as a function to check if a wchar_t is a whitspace character.

Trimming was used to test whether a string was blank or not, and this caused the source syllable texts to be altered when the kanji interpolation algorithm was run.

Originally committed to SVN as r3085.
This commit is contained in:
Niels Martin Hansen 2009-06-24 22:22:45 +00:00
parent a7760db77b
commit beedca2fba
5 changed files with 47 additions and 13 deletions

View file

@ -42,6 +42,7 @@
#include "ass_style.h"
#include "ass_file.h"
#include "ass_override.h"
#include "utils.h"
#ifdef __WINDOWS__
#include "../../contrib/lua51/src/lualib.h"
@ -78,7 +79,7 @@ namespace Automation4 {
lua_pushstring(L, raw.mb_str(wxConvUTF8));
lua_setfield(L, -2, "raw");
if (raw.Trim().IsEmpty()) {
if (StringEmptyOrWhitespace(raw)) {
lua_pushstring(L, "clear");
} else if (raw[0] == _T(';')) {

View file

@ -46,6 +46,7 @@
#include "ass_style.h"
#include "ass_file.h"
#include "ass_override.h"
#include "utils.h"
#include <assert.h>
#include <algorithm>
#include <ruby.h>
@ -67,7 +68,7 @@ namespace Automation4 {
rb_hash_aset(ass_entry, STR2SYM("raw"), rb_str_new2(e->GetEntryData().mb_str(wxConvUTF8)));
VALUE entry_class;
if (raw.Trim().IsEmpty()) {
if (StringEmptyOrWhitespace(raw)) {
entry_class = STR2SYM("clear");
} else if (raw[0] == _T(';')) {

View file

@ -64,11 +64,11 @@ class KaraokeLineMatchDisplay : public wxControl {
struct MatchSyllable {
int dur;
wxString text;
MatchSyllable() : dur(0) { }
MatchSyllable(int _dur, const wxString &_text) : dur(_dur), text(_text) { }
};
struct MatchGroup {
std::vector<MatchSyllable> src;
typedef std::vector<MatchSyllable>::iterator SrcIterator;
std::vector<const MatchSyllable> src;
typedef std::vector<const MatchSyllable>::iterator SrcIterator;
wxString dst;
int duration;
int last_render_width;
@ -79,8 +79,8 @@ class KaraokeLineMatchDisplay : public wxControl {
std::vector<MatchGroup> matched_groups;
typedef std::vector<MatchGroup>::iterator MatchedGroupIterator;
// Unmatched source syllables
std::deque<MatchSyllable> unmatched_source;
typedef std::deque<MatchSyllable>::iterator UnmatchedSourceIterator;
std::deque<const MatchSyllable> unmatched_source;
typedef std::deque<const MatchSyllable>::iterator UnmatchedSourceIterator;
// Unmatched destination text
wxString unmatched_destination;
@ -374,10 +374,7 @@ void KaraokeLineMatchDisplay::SetInputData(const AssDialogue *src, const AssDial
// Start from 1 instead of 0: The first syllable is actually everything before the first
for (size_t i = 1; i < kara.size(); ++i)
{
MatchSyllable syl;
syl.text = kara[i].text;
syl.dur = kara[i].duration;
unmatched_source.push_back(syl);
unmatched_source.push_back(MatchSyllable(kara[i].duration, kara[i].text));
}
delete varsrc;
}
@ -521,7 +518,7 @@ void KaraokeLineMatchDisplay::AutoMatchJapanese()
// Now the source syllable might consist of just whitespace.
// Eat all whitespace at the start of the destination.
if (src.Trim().size() == 0)
if (StringEmptyOrWhitespace(src))
{
trycatchingmorespaces:
// ASCII space
@ -594,7 +591,7 @@ trycatchingmorespaces:
// Yay! Time to interpolate.
// Special case: If the last source syllable before the matching one is
// empty or contains just whitespace, don't include that one.
if (src_lookahead_pos > 1 && unmatched_source[src_lookahead_pos-2].text.Trim().size() == 0)
if (src_lookahead_pos > 1 && StringEmptyOrWhitespace(unmatched_source[src_lookahead_pos-2].text))
src_lookahead_pos -= 1;
// Special case: Just one source syllable matching, pick all destination found
if (src_lookahead_pos == 2)

View file

@ -303,6 +303,39 @@ void GetWordBoundaries(const wxString text,IntPairVector &results,int start,int
}
/////////////////////////////////////////////////////////
// Determine whether wchar 'c' is a whitespace character
bool IsWhitespace(wchar_t c)
{
const wchar_t whitespaces[] = {
// http://en.wikipedia.org/wiki/Space_(punctuation)#Table_of_spaces
0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x0020, 0x0085, 0x00A0,
0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F,
0x025F, 0x3000, 0xFEFF
};
const size_t num_chars = sizeof(whitespaces) / sizeof(whitespaces[0]);
for (size_t i = 0; i < num_chars; ++i)
if (whitespaces[i] == c)
return true;
return false;
}
///////////////////////////////////////////////////////////////
// Returns true if str is empty of consists of only whitespace
bool StringEmptyOrWhitespace(const wxString &str)
{
for (size_t i = 0; i < str.size(); ++i)
if (!IsWhitespace(str[i]))
return false;
return true;
}
/////////////////////
// String to integer
// wxString::ToLong() is slow and not as flexible

View file

@ -68,6 +68,8 @@ wxString PrettySize(int bytes);
wxMenuItem *AppendBitmapMenuItem (wxMenu* parentMenu,int id,wxString text,wxString help,wxBitmap bmp,int pos=-1);
int SmallestPowerOf2(int x);
void GetWordBoundaries(const wxString text,IntPairVector &results,int start=0,int end=-1);
bool IsWhitespace(wchar_t c);
bool StringEmptyOrWhitespace(const wxString &str);
int AegiStringToInt(const wxString &str,int start=0,int end=-1);
int AegiStringToFix(const wxString &str,size_t decimalPlaces,int start=0,int end=-1);
wxIcon BitmapToIcon(wxBitmap bmp);