COMMON: add UnicodeBiDiText wrapper
This commit is contained in:
parent
6a653312e2
commit
ec83715b43
9 changed files with 148 additions and 104 deletions
|
@ -30,7 +30,6 @@ MODULE_OBJS := \
|
|||
rational.o \
|
||||
rendermode.o \
|
||||
str.o \
|
||||
str-bidi.o \
|
||||
str-enc.o \
|
||||
stream.o \
|
||||
system.o \
|
||||
|
@ -38,6 +37,7 @@ MODULE_OBJS := \
|
|||
tokenizer.o \
|
||||
translation.o \
|
||||
unarj.o \
|
||||
unicode-bidi.o \
|
||||
unzip.o \
|
||||
ustr.o \
|
||||
util.o \
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/str-bidi.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#ifdef USE_FRIBIDI
|
||||
#include <fribidi/fribidi.h>
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
String convertBiDiString(const String &input, const Common::CodePage page) {
|
||||
return convertBiDiU32String(input.decode(page)).encode(page);
|
||||
}
|
||||
|
||||
U32String convertBiDiU32String(const U32String &input) {
|
||||
|
||||
#ifdef USE_FRIBIDI
|
||||
int buff_length = (input.size() + 2) * 2; // it's more than enough, but it's better to be on the safe side
|
||||
FriBidiChar *visual_str = (FriBidiChar *)malloc(buff_length * sizeof(FriBidiChar));
|
||||
|
||||
FriBidiCharType pbase_dir = FRIBIDI_TYPE_ON;
|
||||
|
||||
if (!fribidi_log2vis(
|
||||
/* input */
|
||||
(const FriBidiChar *)input.c_str(),
|
||||
input.size(),
|
||||
&pbase_dir,
|
||||
/* output */
|
||||
visual_str,
|
||||
NULL, // position_L_to_V_list,
|
||||
NULL, // position_V_to_L_list,
|
||||
NULL // embedding_level_list
|
||||
)) {
|
||||
warning("convertBiDiU32String: calling fribidi_log2vis failed");
|
||||
free(visual_str);
|
||||
return input;
|
||||
}
|
||||
|
||||
U32String result = U32String(visual_str, input.size());
|
||||
free(visual_str);
|
||||
|
||||
return result;
|
||||
#else
|
||||
warning("convertBiDiU32String: Fribidi not available, using input string as fallback");
|
||||
return input;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int getVisualPosition(const U32String &str, int pos) {
|
||||
Common::U32String suffix(str.c_str() + pos + 1);
|
||||
Common::U32String visual_str = Common::convertBiDiU32String(str);
|
||||
Common::U32String visual_prefix(visual_str.c_str(), suffix.size());
|
||||
Common::U32String visual_suffix = Common::convertBiDiU32String(suffix);
|
||||
return visual_prefix == visual_suffix ? suffix.size() : pos;
|
||||
}
|
||||
|
||||
int getVisualPosition(const String &str, const Common::CodePage page, int logicalPos) {
|
||||
return getVisualPosition(str.decode(page), logicalPos);
|
||||
}
|
||||
|
||||
} // End of namespace Common
|
|
@ -33,7 +33,7 @@
|
|||
#include "common/fs.h"
|
||||
#include "common/system.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "common/str-bidi.h"
|
||||
#include "common/unicode-bidi.h"
|
||||
|
||||
#ifdef USE_TRANSLATION
|
||||
|
||||
|
|
106
common/unicode-bidi.cpp
Normal file
106
common/unicode-bidi.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/ustr.h"
|
||||
#include "common/unicode-bidi.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#ifdef USE_FRIBIDI
|
||||
#include <fribidi/fribidi.h>
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
UnicodeBiDiText::UnicodeBiDiText(const Common::U32String &str) : logical(str), _log_to_vis_index(NULL), _vis_to_log_index(NULL) {
|
||||
initWithU32String(str);
|
||||
}
|
||||
|
||||
UnicodeBiDiText::UnicodeBiDiText(const Common::String &str, const Common::CodePage page) : logical(str), _log_to_vis_index(NULL), _vis_to_log_index(NULL) {
|
||||
initWithU32String(str.decode(page));
|
||||
}
|
||||
|
||||
UnicodeBiDiText::~UnicodeBiDiText() {
|
||||
delete[] _log_to_vis_index;
|
||||
delete[] _vis_to_log_index;
|
||||
}
|
||||
|
||||
uint32 UnicodeBiDiText::getVisualPosition(uint32 logicalPos) const {
|
||||
if (NULL != _log_to_vis_index && logicalPos < size()) {
|
||||
return _log_to_vis_index[logicalPos];
|
||||
}
|
||||
return logicalPos;
|
||||
}
|
||||
uint32 UnicodeBiDiText::getLogicalPosition(uint32 visualPos) const {
|
||||
if (NULL != _log_to_vis_index && visualPos < size()) {
|
||||
return _vis_to_log_index[visualPos];
|
||||
}
|
||||
return visualPos;
|
||||
}
|
||||
|
||||
void UnicodeBiDiText::initWithU32String(const U32String &input) {
|
||||
|
||||
#ifdef USE_FRIBIDI
|
||||
uint32 input_size = input.size();
|
||||
uint32 buff_length = (input_size + 2) * 2; // it's more than enough, but it's better to be on the safe side
|
||||
FriBidiChar *visual_str = new FriBidiChar[buff_length * sizeof(FriBidiChar)];
|
||||
_log_to_vis_index = new uint32[input_size];
|
||||
_vis_to_log_index = new uint32[input_size];
|
||||
FriBidiCharType pbase_dir = FRIBIDI_TYPE_ON;
|
||||
|
||||
if (!fribidi_log2vis(
|
||||
/* input */
|
||||
(const FriBidiChar *)input.c_str(),
|
||||
input_size,
|
||||
&pbase_dir,
|
||||
/* output */
|
||||
visual_str,
|
||||
(FriBidiStrIndex *)_log_to_vis_index, // position_L_to_V_list,
|
||||
(FriBidiStrIndex *)_vis_to_log_index, // position_V_to_L_list,
|
||||
NULL // embedding_level_list
|
||||
)) {
|
||||
warning("initWithU32String: calling fribidi_log2vis failed");
|
||||
delete[] visual_str;
|
||||
delete[] _log_to_vis_index;
|
||||
delete[] _vis_to_log_index;
|
||||
visual = input;
|
||||
_log_to_vis_index = NULL;
|
||||
_vis_to_log_index = NULL;
|
||||
} else {
|
||||
visual = U32String(visual_str, input.size());
|
||||
delete[] visual_str;
|
||||
}
|
||||
#else
|
||||
warning("initWithU32String: Fribidi not available, using input string as fallback");
|
||||
visual = input;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
String convertBiDiString(const String &input, const Common::CodePage page) {
|
||||
return convertBiDiU32String(input.decode(page)).visual.encode(page);
|
||||
}
|
||||
|
||||
UnicodeBiDiText convertBiDiU32String(const U32String &input) {
|
||||
return UnicodeBiDiText(input);
|
||||
}
|
||||
|
||||
} // End of namespace Common
|
|
@ -25,20 +25,30 @@
|
|||
|
||||
#include "common/str.h"
|
||||
#include "common/ustr.h"
|
||||
#include "common/str-enc.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
/*
|
||||
* Wrapper for GNU FriBidi implementation of the Unicode Bidirectional Algorithm
|
||||
* For LTR (Left To Right) languages, returns the original input
|
||||
* For RTL (Right To Left) languages, returns visual representation of a logical single-line input
|
||||
*/
|
||||
U32String convertBiDiU32String(const U32String &input);
|
||||
String convertBiDiString(const String &input, const Common::CodePage page);
|
||||
class UnicodeBiDiText {
|
||||
private:
|
||||
uint32 *_log_to_vis_index; // from fribidi conversion
|
||||
uint32 *_vis_to_log_index; // from fribidi conversion
|
||||
void initWithU32String(const Common::U32String &str);
|
||||
public:
|
||||
const Common::U32String logical; // original string, ordered logically
|
||||
Common::U32String visual; // from fribidi conversion, ordered visually
|
||||
|
||||
int getVisualPosition(const U32String &str, int pos);
|
||||
int getVisualPosition(const String &str, const Common::CodePage page, int pos);
|
||||
UnicodeBiDiText(const Common::U32String &str);
|
||||
UnicodeBiDiText(const Common::String &str, const Common::CodePage page);
|
||||
~UnicodeBiDiText();
|
||||
|
||||
uint32 getVisualPosition(uint32 logicalPos) const;
|
||||
uint32 getLogicalPosition(uint32 visualPos) const;
|
||||
uint32 size() const { return logical.size(); }
|
||||
};
|
||||
|
||||
/* just call the constructor for convenience */
|
||||
UnicodeBiDiText convertBiDiU32String(const U32String &input);
|
||||
String convertBiDiString(const String &input, const Common::CodePage page);
|
||||
|
||||
} // End of namespace Common
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
#include "common/ustr.h"
|
||||
#include "common/memorypool.h"
|
||||
#include "common/util.h"
|
||||
#include "unicode-bidi.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
|
@ -94,6 +95,10 @@ U32String::U32String(const String &str) : _size(0), _str(_storage) {
|
|||
initWithCStr(str.c_str(), str.size());
|
||||
}
|
||||
|
||||
U32String::U32String(const UnicodeBiDiText &txt) : _size(0), _str(_storage) {
|
||||
initWithCStr(txt.visual.c_str(), txt.visual.size());
|
||||
}
|
||||
|
||||
U32String::~U32String() {
|
||||
decRefCount(_extern._refCount);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
namespace Common {
|
||||
|
||||
class String;
|
||||
class UnicodeBiDiText;
|
||||
|
||||
/**
|
||||
* Very simple string class for UTF-32 strings in ScummVM. The main intention
|
||||
|
@ -103,6 +104,9 @@ public:
|
|||
/** Construct a copy of the given string. */
|
||||
U32String(const U32String &str);
|
||||
|
||||
/** Construct a copy of the given unicode BiDi converted string. */
|
||||
U32String(const UnicodeBiDiText &txt);
|
||||
|
||||
/** Construct a new string from the given NULL-terminated C string. */
|
||||
explicit U32String(const char *str);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "common/keyboard.h"
|
||||
#include "common/macresman.h"
|
||||
#include "common/winexe_pe.h"
|
||||
#include "common/str-bidi.h"
|
||||
#include "common/unicode-bidi.h"
|
||||
|
||||
#include "graphics/primitives.h"
|
||||
#include "graphics/font.h"
|
||||
|
@ -744,12 +744,12 @@ static void drawFilledRoundRect(ManagedSurface *surface, Common::Rect &rect, int
|
|||
drawRoundRect(rect, arc, color, true, drawPixelPlain, surface);
|
||||
}
|
||||
|
||||
static void underlineAccelerator(ManagedSurface *dst, const Font *font, const Common::U32String &str, int x, int y, int shortcutPos, uint32 color) {
|
||||
static void underlineAccelerator(ManagedSurface *dst, const Font *font, const Common::UnicodeBiDiText &txt, int x, int y, int shortcutPos, uint32 color) {
|
||||
if (shortcutPos == -1)
|
||||
return;
|
||||
|
||||
int visualPos = getVisualPosition(str, shortcutPos);
|
||||
Common::U32String s = Common::convertBiDiU32String(str);
|
||||
int visualPos = txt.getVisualPosition(shortcutPos);
|
||||
Common::U32String s(txt.visual);
|
||||
|
||||
// Erase characters only if it is not end of the string
|
||||
if ((uint)(visualPos + 1) < s.size())
|
||||
|
@ -813,9 +813,10 @@ bool MacMenu::draw(ManagedSurface *g, bool forceRedraw) {
|
|||
|
||||
if (it->unicode) {
|
||||
int accOff = _align == kTextAlignRight ? it->bbox.width() - _font->getStringWidth(it->unicodeText) : 0;
|
||||
Common::UnicodeBiDiText utxt(it->unicodeText);
|
||||
|
||||
_font->drawString(&_screen, convertBiDiU32String(it->unicodeText), x, y, it->bbox.width(), color, _align);
|
||||
underlineAccelerator(&_screen, _font, it->unicodeText, x + accOff, y, it->shortcutPos, color);
|
||||
_font->drawString(&_screen, utxt.visual, x, y, it->bbox.width(), color, _align);
|
||||
underlineAccelerator(&_screen, _font, utxt, x + accOff, y, it->shortcutPos, color);
|
||||
} else {
|
||||
const Font *font = getMenuFont(it->style);
|
||||
|
||||
|
@ -896,8 +897,9 @@ void MacMenu::renderSubmenu(MacMenuSubMenu *menu, bool recursive) {
|
|||
}
|
||||
|
||||
if (menu->items[i]->unicode) {
|
||||
_font->drawString(s, convertBiDiU32String(unicodeText), tx, ty, r->width(), color, _align);
|
||||
underlineAccelerator(s, _font, unicodeText, tx + accOff, ty, shortcutPos, color);
|
||||
Common::UnicodeBiDiText utxt(unicodeText);
|
||||
_font->drawString(s, utxt.visual, tx, ty, r->width(), color, _align);
|
||||
underlineAccelerator(s, _font, utxt, tx + accOff, ty, shortcutPos, color);
|
||||
} else {
|
||||
const Font *font = getMenuFont(menu->items[i]->style);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "common/str-bidi.h"
|
||||
#include "common/unicode-bidi.h"
|
||||
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
#include "graphics/macgui/mactext.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue