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

View file

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

View file

@ -64,11 +64,11 @@ class KaraokeLineMatchDisplay : public wxControl {
struct MatchSyllable { struct MatchSyllable {
int dur; int dur;
wxString text; wxString text;
MatchSyllable() : dur(0) { } MatchSyllable(int _dur, const wxString &_text) : dur(_dur), text(_text) { }
}; };
struct MatchGroup { struct MatchGroup {
std::vector<MatchSyllable> src; std::vector<const MatchSyllable> src;
typedef std::vector<MatchSyllable>::iterator SrcIterator; typedef std::vector<const MatchSyllable>::iterator SrcIterator;
wxString dst; wxString dst;
int duration; int duration;
int last_render_width; int last_render_width;
@ -79,8 +79,8 @@ class KaraokeLineMatchDisplay : public wxControl {
std::vector<MatchGroup> matched_groups; std::vector<MatchGroup> matched_groups;
typedef std::vector<MatchGroup>::iterator MatchedGroupIterator; typedef std::vector<MatchGroup>::iterator MatchedGroupIterator;
// Unmatched source syllables // Unmatched source syllables
std::deque<MatchSyllable> unmatched_source; std::deque<const MatchSyllable> unmatched_source;
typedef std::deque<MatchSyllable>::iterator UnmatchedSourceIterator; typedef std::deque<const MatchSyllable>::iterator UnmatchedSourceIterator;
// Unmatched destination text // Unmatched destination text
wxString unmatched_destination; 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 // Start from 1 instead of 0: The first syllable is actually everything before the first
for (size_t i = 1; i < kara.size(); ++i) for (size_t i = 1; i < kara.size(); ++i)
{ {
MatchSyllable syl; unmatched_source.push_back(MatchSyllable(kara[i].duration, kara[i].text));
syl.text = kara[i].text;
syl.dur = kara[i].duration;
unmatched_source.push_back(syl);
} }
delete varsrc; delete varsrc;
} }
@ -521,7 +518,7 @@ void KaraokeLineMatchDisplay::AutoMatchJapanese()
// Now the source syllable might consist of just whitespace. // Now the source syllable might consist of just whitespace.
// Eat all whitespace at the start of the destination. // Eat all whitespace at the start of the destination.
if (src.Trim().size() == 0) if (StringEmptyOrWhitespace(src))
{ {
trycatchingmorespaces: trycatchingmorespaces:
// ASCII space // ASCII space
@ -594,7 +591,7 @@ trycatchingmorespaces:
// Yay! Time to interpolate. // Yay! Time to interpolate.
// Special case: If the last source syllable before the matching one is // Special case: If the last source syllable before the matching one is
// empty or contains just whitespace, don't include that one. // 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; src_lookahead_pos -= 1;
// Special case: Just one source syllable matching, pick all destination found // Special case: Just one source syllable matching, pick all destination found
if (src_lookahead_pos == 2) 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 // String to integer
// wxString::ToLong() is slow and not as flexible // 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); wxMenuItem *AppendBitmapMenuItem (wxMenu* parentMenu,int id,wxString text,wxString help,wxBitmap bmp,int pos=-1);
int SmallestPowerOf2(int x); int SmallestPowerOf2(int x);
void GetWordBoundaries(const wxString text,IntPairVector &results,int start=0,int end=-1); 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 AegiStringToInt(const wxString &str,int start=0,int end=-1);
int AegiStringToFix(const wxString &str,size_t decimalPlaces,int start=0,int end=-1); int AegiStringToFix(const wxString &str,size_t decimalPlaces,int start=0,int end=-1);
wxIcon BitmapToIcon(wxBitmap bmp); wxIcon BitmapToIcon(wxBitmap bmp);