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 \
|
rational.o \
|
||||||
rendermode.o \
|
rendermode.o \
|
||||||
str.o \
|
str.o \
|
||||||
str-bidi.o \
|
|
||||||
str-enc.o \
|
str-enc.o \
|
||||||
stream.o \
|
stream.o \
|
||||||
system.o \
|
system.o \
|
||||||
|
@ -38,6 +37,7 @@ MODULE_OBJS := \
|
||||||
tokenizer.o \
|
tokenizer.o \
|
||||||
translation.o \
|
translation.o \
|
||||||
unarj.o \
|
unarj.o \
|
||||||
|
unicode-bidi.o \
|
||||||
unzip.o \
|
unzip.o \
|
||||||
ustr.o \
|
ustr.o \
|
||||||
util.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/fs.h"
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
#include "common/textconsole.h"
|
#include "common/textconsole.h"
|
||||||
#include "common/str-bidi.h"
|
#include "common/unicode-bidi.h"
|
||||||
|
|
||||||
#ifdef USE_TRANSLATION
|
#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/str.h"
|
||||||
#include "common/ustr.h"
|
#include "common/ustr.h"
|
||||||
#include "common/str-enc.h"
|
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
/*
|
class UnicodeBiDiText {
|
||||||
* Wrapper for GNU FriBidi implementation of the Unicode Bidirectional Algorithm
|
private:
|
||||||
* For LTR (Left To Right) languages, returns the original input
|
uint32 *_log_to_vis_index; // from fribidi conversion
|
||||||
* For RTL (Right To Left) languages, returns visual representation of a logical single-line input
|
uint32 *_vis_to_log_index; // from fribidi conversion
|
||||||
*/
|
void initWithU32String(const Common::U32String &str);
|
||||||
U32String convertBiDiU32String(const U32String &input);
|
public:
|
||||||
String convertBiDiString(const String &input, const Common::CodePage page);
|
const Common::U32String logical; // original string, ordered logically
|
||||||
|
Common::U32String visual; // from fribidi conversion, ordered visually
|
||||||
|
|
||||||
int getVisualPosition(const U32String &str, int pos);
|
UnicodeBiDiText(const Common::U32String &str);
|
||||||
int getVisualPosition(const String &str, const Common::CodePage page, int pos);
|
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
|
} // End of namespace Common
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "common/ustr.h"
|
#include "common/ustr.h"
|
||||||
#include "common/memorypool.h"
|
#include "common/memorypool.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
#include "unicode-bidi.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
|
@ -94,6 +95,10 @@ U32String::U32String(const String &str) : _size(0), _str(_storage) {
|
||||||
initWithCStr(str.c_str(), str.size());
|
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() {
|
U32String::~U32String() {
|
||||||
decRefCount(_extern._refCount);
|
decRefCount(_extern._refCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
|
class UnicodeBiDiText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Very simple string class for UTF-32 strings in ScummVM. The main intention
|
* 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. */
|
/** Construct a copy of the given string. */
|
||||||
U32String(const U32String &str);
|
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. */
|
/** Construct a new string from the given NULL-terminated C string. */
|
||||||
explicit U32String(const char *str);
|
explicit U32String(const char *str);
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "common/keyboard.h"
|
#include "common/keyboard.h"
|
||||||
#include "common/macresman.h"
|
#include "common/macresman.h"
|
||||||
#include "common/winexe_pe.h"
|
#include "common/winexe_pe.h"
|
||||||
#include "common/str-bidi.h"
|
#include "common/unicode-bidi.h"
|
||||||
|
|
||||||
#include "graphics/primitives.h"
|
#include "graphics/primitives.h"
|
||||||
#include "graphics/font.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);
|
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)
|
if (shortcutPos == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int visualPos = getVisualPosition(str, shortcutPos);
|
int visualPos = txt.getVisualPosition(shortcutPos);
|
||||||
Common::U32String s = Common::convertBiDiU32String(str);
|
Common::U32String s(txt.visual);
|
||||||
|
|
||||||
// Erase characters only if it is not end of the string
|
// Erase characters only if it is not end of the string
|
||||||
if ((uint)(visualPos + 1) < s.size())
|
if ((uint)(visualPos + 1) < s.size())
|
||||||
|
@ -813,9 +813,10 @@ bool MacMenu::draw(ManagedSurface *g, bool forceRedraw) {
|
||||||
|
|
||||||
if (it->unicode) {
|
if (it->unicode) {
|
||||||
int accOff = _align == kTextAlignRight ? it->bbox.width() - _font->getStringWidth(it->unicodeText) : 0;
|
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);
|
_font->drawString(&_screen, utxt.visual, x, y, it->bbox.width(), color, _align);
|
||||||
underlineAccelerator(&_screen, _font, it->unicodeText, x + accOff, y, it->shortcutPos, color);
|
underlineAccelerator(&_screen, _font, utxt, x + accOff, y, it->shortcutPos, color);
|
||||||
} else {
|
} else {
|
||||||
const Font *font = getMenuFont(it->style);
|
const Font *font = getMenuFont(it->style);
|
||||||
|
|
||||||
|
@ -896,8 +897,9 @@ void MacMenu::renderSubmenu(MacMenuSubMenu *menu, bool recursive) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menu->items[i]->unicode) {
|
if (menu->items[i]->unicode) {
|
||||||
_font->drawString(s, convertBiDiU32String(unicodeText), tx, ty, r->width(), color, _align);
|
Common::UnicodeBiDiText utxt(unicodeText);
|
||||||
underlineAccelerator(s, _font, unicodeText, tx + accOff, ty, shortcutPos, color);
|
_font->drawString(s, utxt.visual, tx, ty, r->width(), color, _align);
|
||||||
|
underlineAccelerator(s, _font, utxt, tx + accOff, ty, shortcutPos, color);
|
||||||
} else {
|
} else {
|
||||||
const Font *font = getMenuFont(menu->items[i]->style);
|
const Font *font = getMenuFont(menu->items[i]->style);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* 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/macfontmanager.h"
|
||||||
#include "graphics/macgui/mactext.h"
|
#include "graphics/macgui/mactext.h"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue