[Scummvm-cvs-logs] scummvm master -> e718719f918a4941fd72d3b245922a834bc5a5d2

lordhoto lordhoto at gmail.com
Tue Nov 26 11:24:38 CET 2013


This automated email contains information about 10 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
1a6f9378aa COMMON: Add underlying type names to Common::String.
b90400da44 COMMON: Add simple UTF-32 string class U32String.
afa3f50b8a GRAPHICS: Let Font take uint32 as character codes.
13d470dc61 GRAPHICS: Get rid of _glyphSlots in TTFFont.
09c634dd55 GRAPHICS: Allow TTFFont to cache glyphs when required.
9da09f5846 GRAPHICS: Allow Font to accept U32String as strings.
a6fff7a805 WINTERMUTE: Switch WideString to U32String.
4c15e51ab5 COMMON: Document U32String a bit better.
abe6d30f36 COMMON: Document Common::String::unsigned_type.
e718719f91 Merge pull request #411 from lordhoto/unicode


Commit: 1a6f9378aa32b3d2877c1ee90e212bde82ef832b
    https://github.com/scummvm/scummvm/commit/1a6f9378aa32b3d2877c1ee90e212bde82ef832b
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:54-08:00

Commit Message:
COMMON: Add underlying type names to Common::String.

The value_type is analogous to std::basic_string::value_type.
The unsigned_type on the other hand is an unsigned type of the value_type which
allows to obtain an character without nasty sign extension.

Changed paths:
    common/str.h



diff --git a/common/str.h b/common/str.h
index 6b4475e..2ad2626 100644
--- a/common/str.h
+++ b/common/str.h
@@ -234,6 +234,8 @@ public:
 	static String vformat(const char *fmt, va_list args);
 
 public:
+	typedef char          value_type;
+	typedef unsigned char unsigned_type;
 	typedef char *        iterator;
 	typedef const char *  const_iterator;
 


Commit: b90400da44e4438c5a00773e6d2af82880dc45f4
    https://github.com/scummvm/scummvm/commit/b90400da44e4438c5a00773e6d2af82880dc45f4
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:54-08:00

Commit Message:
COMMON: Add simple UTF-32 string class U32String.

Changed paths:
  A common/ustr.cpp
  A common/ustr.h
    common/module.mk



diff --git a/common/module.mk b/common/module.mk
index 1b34d15..67c498d 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -35,6 +35,7 @@ MODULE_OBJS := \
 	translation.o \
 	unarj.o \
 	unzip.o \
+	ustr.o \
 	util.o \
 	winexe.o \
 	winexe_ne.o \
diff --git a/common/ustr.cpp b/common/ustr.cpp
new file mode 100644
index 0000000..fbc831c
--- /dev/null
+++ b/common/ustr.cpp
@@ -0,0 +1,329 @@
+/* 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/memorypool.h"
+#include "common/util.h"
+
+namespace Common {
+
+extern MemoryPool *g_refCountPool;
+
+static uint32 computeCapacity(uint32 len) {
+	// By default, for the capacity we use the next multiple of 32
+	return ((len + 32 - 1) & ~0x1F);
+}
+
+U32String::U32String(const value_type *str) : _size(0), _str(_storage) {
+	if (str == 0) {
+		_storage[0] = 0;
+		_size = 0;
+	} else {
+		uint32 len = 0;
+		const value_type *s = str;
+		while (*s++) {
+			++len;
+		}
+		initWithCStr(str, len);
+	}
+}
+
+U32String::U32String(const value_type *str, uint32 len) : _size(0), _str(_storage) {
+	initWithCStr(str, len);
+}
+
+U32String::U32String(const value_type *beginP, const value_type *endP) : _size(0), _str(_storage) {
+	assert(endP >= beginP);
+	initWithCStr(beginP, endP - beginP);
+}
+
+U32String::U32String(const U32String &str)
+    : _size(str._size) {
+	if (str.isStorageIntern()) {
+		// String in internal storage: just copy it
+		memcpy(_storage, str._storage, _builtinCapacity * sizeof(value_type));
+		_str = _storage;
+	} else {
+		// String in external storage: use refcount mechanism
+		str.incRefCount();
+		_extern._refCount = str._extern._refCount;
+		_extern._capacity = str._extern._capacity;
+		_str = str._str;
+	}
+	assert(_str != 0);
+}
+
+U32String::~U32String() {
+	decRefCount(_extern._refCount);
+}
+
+U32String &U32String::operator=(const U32String &str) {
+	if (&str == this)
+		return *this;
+
+	if (str.isStorageIntern()) {
+		decRefCount(_extern._refCount);
+		_size = str._size;
+		_str = _storage;
+		memcpy(_str, str._str, (_size + 1) * sizeof(value_type));
+	} else {
+		str.incRefCount();
+		decRefCount(_extern._refCount);
+
+		_extern._refCount = str._extern._refCount;
+		_extern._capacity = str._extern._capacity;
+		_size = str._size;
+		_str = str._str;
+	}
+
+	return *this;
+}
+
+U32String &U32String::operator+=(const U32String &str) {
+	if (&str == this) {
+		return operator+=(U32String(str));
+	}
+
+	int len = str._size;
+	if (len > 0) {
+		ensureCapacity(_size + len, true);
+
+		memcpy(_str + _size, str._str, (len + 1) * sizeof(value_type));
+		_size += len;
+	}
+	return *this;
+}
+
+U32String &U32String::operator+=(value_type c) {
+	ensureCapacity(_size + 1, true);
+
+	_str[_size++] = c;
+	_str[_size] = 0;
+
+	return *this;
+}
+
+bool U32String::equals(const U32String &x) const {
+	if (this == &x || _str == x._str) {
+		return true;
+	}
+
+	if (x.size() != _size) {
+		return false;
+	}
+
+	return !memcmp(_str, x._str, _size * sizeof(value_type));
+}
+
+bool U32String::contains(value_type x) const {
+	for (uint32 i = 0; i < _size; ++i) {
+		if (_str[i] == x) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void U32String::deleteChar(uint32 p) {
+	assert(p < _size);
+
+	makeUnique();
+	while (p++ < _size)
+		_str[p - 1] = _str[p];
+	_size--;
+}
+
+void U32String::clear() {
+	decRefCount(_extern._refCount);
+
+	_size = 0;
+	_str = _storage;
+	_storage[0] = 0;
+}
+
+void U32String::toLowercase() {
+	makeUnique();
+	for (uint32 i = 0; i < _size; ++i) {
+		if (_str[i] < 128) {
+			_str[i] = tolower(_str[i]);
+		}
+	}
+}
+
+void U32String::toUppercase() {
+	makeUnique();
+	for (uint32 i = 0; i < _size; ++i) {
+		if (_str[i] < 128) {
+			_str[i] = toupper(_str[i]);
+		}
+	}
+}
+
+uint32 U32String::find(const U32String &str, uint32 pos) const {
+	if (pos >= _size) {
+		return npos;
+	}
+
+	const value_type *strP = str.c_str();
+
+	for (const_iterator cur = begin() + pos; *cur; ++cur) {
+		uint i = 0;
+		while (true) {
+			if (!strP[i]) {
+				return cur - begin();
+			}
+
+			if (cur[i] != strP[i]) {
+				break;
+			}
+
+			++i;
+		}
+	}
+
+	return npos;
+}
+
+void U32String::makeUnique() {
+	ensureCapacity(_size, true);
+}
+
+void U32String::ensureCapacity(uint32 new_size, bool keep_old) {
+	bool isShared;
+	uint32 curCapacity, newCapacity;
+	value_type *newStorage;
+	int *oldRefCount = _extern._refCount;
+
+	if (isStorageIntern()) {
+		isShared = false;
+		curCapacity = _builtinCapacity;
+	} else {
+		isShared = (oldRefCount && *oldRefCount > 1);
+		curCapacity = _extern._capacity;
+	}
+
+	// Special case: If there is enough space, and we do not share
+	// the storage, then there is nothing to do.
+	if (!isShared && new_size < curCapacity)
+		return;
+
+	if (isShared && new_size < _builtinCapacity) {
+		// We share the storage, but there is enough internal storage: Use that.
+		newStorage = _storage;
+		newCapacity = _builtinCapacity;
+	} else {
+		// We need to allocate storage on the heap!
+
+		// Compute a suitable new capacity limit
+		// If the current capacity is sufficient we use the same capacity
+		if (new_size < curCapacity)
+			newCapacity = curCapacity;
+		else
+			newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1));
+
+		// Allocate new storage
+		newStorage = new value_type[newCapacity];
+		assert(newStorage);
+	}
+
+	// Copy old data if needed, elsewise reset the new storage.
+	if (keep_old) {
+		assert(_size < newCapacity);
+		memcpy(newStorage, _str, (_size + 1) * sizeof(value_type));
+	} else {
+		_size = 0;
+		newStorage[0] = 0;
+	}
+
+	// Release hold on the old storage ...
+	decRefCount(oldRefCount);
+
+	// ... in favor of the new storage
+	_str = newStorage;
+
+	if (!isStorageIntern()) {
+		// Set the ref count & capacity if we use an external storage.
+		// It is important to do this *after* copying any old content,
+		// else we would override data that has not yet been copied!
+		_extern._refCount = 0;
+		_extern._capacity = newCapacity;
+	}
+}
+
+void U32String::incRefCount() const {
+	assert(!isStorageIntern());
+	if (_extern._refCount == 0) {
+		if (g_refCountPool == 0) {
+			g_refCountPool = new MemoryPool(sizeof(int));
+			assert(g_refCountPool);
+		}
+
+		_extern._refCount = (int *)g_refCountPool->allocChunk();
+		*_extern._refCount = 2;
+	} else {
+		++(*_extern._refCount);
+	}
+}
+
+void U32String::decRefCount(int *oldRefCount) {
+	if (isStorageIntern())
+		return;
+
+	if (oldRefCount) {
+		--(*oldRefCount);
+	}
+	if (!oldRefCount || *oldRefCount <= 0) {
+		// The ref count reached zero, so we free the string storage
+		// and the ref count storage.
+		if (oldRefCount) {
+			assert(g_refCountPool);
+			g_refCountPool->freeChunk(oldRefCount);
+		}
+		delete[] _str;
+
+		// Even though _str points to a freed memory block now,
+		// we do not change its value, because any code that calls
+		// decRefCount will have to do this afterwards anyway.
+	}
+}
+
+void U32String::initWithCStr(const value_type *str, uint32 len) {
+	assert(str);
+
+	_storage[0] = 0;
+
+	_size = len;
+
+	if (len >= _builtinCapacity) {
+		// Not enough internal storage, so allocate more
+		_extern._capacity = computeCapacity(len+1);
+		_extern._refCount = 0;
+		_str = new value_type[_extern._capacity];
+		assert(_str != 0);
+	}
+
+	// Copy the string into the storage area
+	memmove(_str, str, len * sizeof(value_type));
+	_str[len] = 0;
+}
+
+} // End of namespace Common
diff --git a/common/ustr.h b/common/ustr.h
new file mode 100644
index 0000000..e549c5f
--- /dev/null
+++ b/common/ustr.h
@@ -0,0 +1,155 @@
+/* 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.
+ */
+
+#ifndef COMMON_USTR_H
+#define COMMON_USTR_H
+
+#include "common/scummsys.h"
+
+namespace Common {
+
+class U32String {
+public:
+	static const uint32 npos = 0xFFFFFFFF;
+
+	typedef uint32 value_type;
+	typedef uint32 unsigned_type;
+private:
+	/**
+	 * The size of the internal storage. Increasing this means less heap
+	 * allocations are needed, at the cost of more stack memory usage,
+	 * and of course lots of wasted memory.
+	 */
+	static const uint32 _builtinCapacity = 32;
+
+	/**
+	 * Length of the string.
+	 */
+	uint32 _size;
+
+	/**
+	 * Pointer to the actual string storage. Either points to _storage,
+	 * or to a block allocated on the heap via malloc.
+	 */
+	value_type  *_str;
+
+
+	union {
+		/**
+		 * Internal string storage.
+		 */
+		value_type _storage[_builtinCapacity];
+		/**
+		 * External string storage data -- the refcounter, and the
+		 * capacity of the string _str points to.
+		 */
+		struct {
+			mutable int *_refCount;
+			uint32       _capacity;
+		} _extern;
+	};
+
+	inline bool isStorageIntern() const {
+		return _str == _storage;
+	}
+
+public:
+	U32String() : _size(0), _str(_storage) { _storage[0] = 0; }
+
+	explicit U32String(const value_type *str);
+
+	U32String(const value_type *str, uint32 len);
+
+	U32String(const value_type *beginP, const value_type *endP);
+
+	U32String(const U32String &str);
+
+	~U32String();
+
+	U32String &operator=(const U32String &str);
+	U32String &operator+=(const U32String &str);
+	U32String &operator+=(value_type c);
+
+	bool operator==(const U32String &x) const { return equals(x); }
+
+	bool equals(const U32String &x) const;
+
+	bool contains(value_type x) const;
+
+	inline const value_type *c_str() const { return _str; }
+	inline uint32 size() const             { return _size; }
+
+	inline bool empty() const { return (_size == 0); }
+
+	value_type operator[](int idx) const {
+		assert(_str && idx >= 0 && idx < (int)_size);
+		return _str[idx];
+	}
+
+	/** Remove the character at position p from the string. */
+	void deleteChar(uint32 p);
+
+	/** Clears the string, making it empty. */
+	void clear();
+
+	/** Convert all characters in the string to lowercase. */
+	void toLowercase();
+
+	/** Convert all characters in the string to uppercase. */
+	void toUppercase();
+
+	uint32 find(const U32String &str, uint32 pos = 0) const;
+
+	typedef value_type *        iterator;
+	typedef const value_type *  const_iterator;
+
+	iterator begin() {
+		// Since the user could potentially
+		// change the string via the returned
+		// iterator we have to assure we are
+		// pointing to a unique storage.
+		makeUnique();
+
+		return _str;
+	}
+
+	iterator end() {
+		return begin() + size();
+	}
+
+	const_iterator begin() const {
+		return _str;
+	}
+
+	const_iterator end() const {
+		return begin() + size();
+	}
+private:
+	void makeUnique();
+	void ensureCapacity(uint32 new_size, bool keep_old);
+	void incRefCount() const;
+	void decRefCount(int *oldRefCount);
+	void initWithCStr(const value_type *str, uint32 len);
+};
+
+} // End of namespace Common
+
+#endif


Commit: afa3f50b8a2bc47a243156c196f88ab799fe4f8f
    https://github.com/scummvm/scummvm/commit/afa3f50b8a2bc47a243156c196f88ab799fe4f8f
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:54-08:00

Commit Message:
GRAPHICS: Let Font take uint32 as character codes.

This is required to support UTF-32 strings but does not make them work
automatically!

Changed paths:
    engines/groovie/font.cpp
    engines/groovie/font.h
    graphics/font.cpp
    graphics/font.h
    graphics/fonts/bdf.cpp
    graphics/fonts/bdf.h
    graphics/fonts/ttf.cpp
    graphics/fonts/winfont.cpp
    graphics/fonts/winfont.h



diff --git a/engines/groovie/font.cpp b/engines/groovie/font.cpp
index d29c22d..a55d8fa 100644
--- a/engines/groovie/font.cpp
+++ b/engines/groovie/font.cpp
@@ -112,7 +112,7 @@ bool T7GFont::load(Common::SeekableReadStream &stream) {
 	return true;
 }
 
-void T7GFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const {
+void T7GFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
 	// We ignore the color, as the font is already colored
 	const Glyph *glyph = getGlyph(chr);
 	const byte *src = glyph->pixels;
@@ -125,7 +125,7 @@ void T7GFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 co
 	}
 }
 
-const T7GFont::Glyph *T7GFont::getGlyph(byte chr) const {
+const T7GFont::Glyph *T7GFont::getGlyph(uint32 chr) const {
 	assert (chr < 128);
 
 	byte numGlyph = _mapChar2Glyph[chr];
diff --git a/engines/groovie/font.h b/engines/groovie/font.h
index 20aaa4c..49cf4b7 100644
--- a/engines/groovie/font.h
+++ b/engines/groovie/font.h
@@ -37,8 +37,8 @@ public:
 
 	int getFontHeight() const { return _maxHeight; }
 	int getMaxCharWidth() const { return _maxWidth; }
-	int getCharWidth(byte chr) const { return getGlyph(chr)->width; }
-	void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const;
+	int getCharWidth(uint32 chr) const { return getGlyph(chr)->width; }
+	void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const;
 
 private:
 	int _maxHeight, _maxWidth;
@@ -55,7 +55,7 @@ private:
 
 	byte _mapChar2Glyph[128];
 	Glyph *_glyphs;
-	const Glyph *getGlyph(byte chr) const;
+	const Glyph *getGlyph(uint32 chr) const;
 };
 
 } // End of Groovie namespace
diff --git a/graphics/font.cpp b/graphics/font.cpp
index a852274..519d63a 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -26,7 +26,7 @@
 
 namespace Graphics {
 
-int Font::getKerningOffset(byte left, byte right) const {
+int Font::getKerningOffset(uint32 left, uint32 right) const {
 	return 0;
 }
 
diff --git a/graphics/font.h b/graphics/font.h
index 6819b42..62538e3 100644
--- a/graphics/font.h
+++ b/graphics/font.h
@@ -70,7 +70,7 @@ public:
 	 * @param chr The character to query the width of.
 	 * @return The character's width.
 	 */
-	virtual int getCharWidth(byte chr) const = 0;
+	virtual int getCharWidth(uint32 chr) const = 0;
 
 	/**
 	 * Query the kerning offset between two characters.
@@ -79,7 +79,7 @@ public:
 	 * @param right The right character. May be 0.
 	 * @return The horizontal displacement.
 	 */
-	virtual int getKerningOffset(byte left, byte right) const;
+	virtual int getKerningOffset(uint32 left, uint32 right) const;
 
 	/**
 	 * Draw a character at a specific point on a surface.
@@ -96,7 +96,7 @@ public:
 	 * @param y   The y coordinate where to draw the character.
 	 * @param color The color of the character.
 	 */
-	virtual void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const = 0;
+	virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const = 0;
 
 	// TODO: Add doxygen comments to this
 	void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
diff --git a/graphics/fonts/bdf.cpp b/graphics/fonts/bdf.cpp
index e523a36..7b2290c 100644
--- a/graphics/fonts/bdf.cpp
+++ b/graphics/fonts/bdf.cpp
@@ -51,7 +51,7 @@ int BdfFont::getMaxCharWidth() const {
 	return _data.maxAdvance;
 }
 
-int BdfFont::getCharWidth(byte chr) const {
+int BdfFont::getCharWidth(uint32 chr) const {
 	// In case all font have the same advance value, we use the maximum.
 	if (!_data.advances)
 		return _data.maxAdvance;
@@ -85,9 +85,9 @@ void drawCharIntern(byte *ptr, uint pitch, const byte *src, int h, int width, in
 	}
 }
 
-int BdfFont::mapToIndex(byte ch) const {
+int BdfFont::mapToIndex(uint32 ch) const {
 	// Check whether the character is included
-	if (_data.firstCharacter <= ch && ch <= _data.firstCharacter + _data.numCharacters) {
+	if (_data.firstCharacter <= (int)ch && (int)ch <= _data.firstCharacter + _data.numCharacters) {
 		if (_data.bitmaps[ch - _data.firstCharacter])
 			return ch - _data.firstCharacter;
 	}
@@ -95,7 +95,7 @@ int BdfFont::mapToIndex(byte ch) const {
 	return _data.defaultCharacter - _data.firstCharacter;
 }
 
-void BdfFont::drawChar(Surface *dst, byte chr, const int tx, const int ty, const uint32 color) const {
+void BdfFont::drawChar(Surface *dst, uint32 chr, const int tx, const int ty, const uint32 color) const {
 	assert(dst != 0);
 
 	// TODO: Where is the relation between the max advance being smaller or
diff --git a/graphics/fonts/bdf.h b/graphics/fonts/bdf.h
index b0166a2..842e54f 100644
--- a/graphics/fonts/bdf.h
+++ b/graphics/fonts/bdf.h
@@ -61,14 +61,14 @@ public:
 	virtual int getFontHeight() const;
 	virtual int getMaxCharWidth() const;
 
-	virtual int getCharWidth(byte chr) const;
-	virtual void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const;
+	virtual int getCharWidth(uint32 chr) const;
+	virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
 
 	static BdfFont *loadFont(Common::SeekableReadStream &stream);
 	static bool cacheFontData(const BdfFont &font, const Common::String &filename);
 	static BdfFont *loadFromCache(Common::SeekableReadStream &stream);
 private:
-	int mapToIndex(byte ch) const;
+	int mapToIndex(uint32 ch) const;
 
 	const BdfFontData _data;
 	const DisposeAfterUse::Flag _dispose;
diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp
index b9e9610..f5bd67f 100644
--- a/graphics/fonts/ttf.cpp
+++ b/graphics/fonts/ttf.cpp
@@ -107,11 +107,11 @@ public:
 
 	virtual int getMaxCharWidth() const;
 
-	virtual int getCharWidth(byte chr) const;
+	virtual int getCharWidth(uint32 chr) const;
 
-	virtual int getKerningOffset(byte left, byte right) const;
+	virtual int getKerningOffset(uint32 left, uint32 right) const;
 
-	virtual void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const;
+	virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
 private:
 	bool _initialized;
 	FT_Face _face;
@@ -129,7 +129,7 @@ private:
 	};
 
 	bool cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr);
-	typedef Common::HashMap<byte, Glyph> GlyphCache;
+	typedef Common::HashMap<uint32, Glyph> GlyphCache;
 	GlyphCache _glyphs;
 
 	FT_UInt _glyphSlots[256];
@@ -243,7 +243,7 @@ int TTFFont::getMaxCharWidth() const {
 	return _width;
 }
 
-int TTFFont::getCharWidth(byte chr) const {
+int TTFFont::getCharWidth(uint32 chr) const {
 	GlyphCache::const_iterator glyphEntry = _glyphs.find(chr);
 	if (glyphEntry == _glyphs.end())
 		return 0;
@@ -251,10 +251,14 @@ int TTFFont::getCharWidth(byte chr) const {
 		return glyphEntry->_value.advance;
 }
 
-int TTFFont::getKerningOffset(byte left, byte right) const {
+int TTFFont::getKerningOffset(uint32 left, uint32 right) const {
 	if (!_hasKerning)
 		return 0;
 
+	if (left > 255 || right > 255) {
+		return 0;
+	}
+
 	FT_UInt leftGlyph = _glyphSlots[left];
 	FT_UInt rightGlyph = _glyphSlots[right];
 
@@ -304,7 +308,7 @@ void renderGlyph(uint8 *dstPos, const int dstPitch, const uint8 *srcPos, const i
 
 } // End of anonymous namespace
 
-void TTFFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const {
+void TTFFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
 	GlyphCache::const_iterator glyphEntry = _glyphs.find(chr);
 	if (glyphEntry == _glyphs.end())
 		return;
diff --git a/graphics/fonts/winfont.cpp b/graphics/fonts/winfont.cpp
index 3bad922..c0ebab1 100644
--- a/graphics/fonts/winfont.cpp
+++ b/graphics/fonts/winfont.cpp
@@ -200,7 +200,7 @@ char WinFont::indexToCharacter(uint16 index) const {
 	return index + _firstChar;
 }
 
-uint16 WinFont::characterToIndex(byte character) const {
+uint16 WinFont::characterToIndex(uint32 character) const {
 	// Go to the default character if we didn't find a mapping
 	if (character < _firstChar || character > _lastChar)
 		character = _defaultChar;
@@ -208,7 +208,7 @@ uint16 WinFont::characterToIndex(byte character) const {
 	return character - _firstChar;
 }
 
-int WinFont::getCharWidth(byte chr) const {
+int WinFont::getCharWidth(uint32 chr) const {
 	return _glyphs[characterToIndex(chr)].charWidth;
 }
 
@@ -324,7 +324,7 @@ bool WinFont::loadFromFNT(Common::SeekableReadStream &stream) {
 	return true;
 }
 
-void WinFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const {
+void WinFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
 	assert(dst);
 	assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
 	assert(_glyphs);
diff --git a/graphics/fonts/winfont.h b/graphics/fonts/winfont.h
index 4382d7e..2c7ba07 100644
--- a/graphics/fonts/winfont.h
+++ b/graphics/fonts/winfont.h
@@ -62,8 +62,8 @@ public:
 	// Font API
 	int getFontHeight() const { return _pixHeight; }
 	int getMaxCharWidth() const { return _maxWidth; }
-	int getCharWidth(byte chr) const;
-	void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const;
+	int getCharWidth(uint32 chr) const;
+	void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
 
 private:
 	bool loadFromPE(const Common::String &fileName, const WinFontDirEntry &dirEntry);
@@ -72,7 +72,7 @@ private:
 	uint32 getFontIndex(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry);
 	bool loadFromFNT(Common::SeekableReadStream &stream);
 	char indexToCharacter(uint16 index) const;
-	uint16 characterToIndex(byte character) const;
+	uint16 characterToIndex(uint32 character) const;
 
 	uint16 _pixHeight;
 	uint16 _maxWidth;


Commit: 13d470dc61049f231a5ed5a71ce8af111612aba2
    https://github.com/scummvm/scummvm/commit/13d470dc61049f231a5ed5a71ce8af111612aba2
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:54-08:00

Commit Message:
GRAPHICS: Get rid of _glyphSlots in TTFFont.

Changed paths:
    graphics/fonts/ttf.cpp



diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp
index f5bd67f..7c48bdf 100644
--- a/graphics/fonts/ttf.cpp
+++ b/graphics/fonts/ttf.cpp
@@ -126,21 +126,20 @@ private:
 		Surface image;
 		int xOffset, yOffset;
 		int advance;
+		FT_UInt slot;
 	};
 
-	bool cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr);
+	bool cacheGlyph(Glyph &glyph, uint chr);
 	typedef Common::HashMap<uint32, Glyph> GlyphCache;
 	GlyphCache _glyphs;
 
-	FT_UInt _glyphSlots[256];
-
 	bool _monochrome;
 	bool _hasKerning;
 };
 
 TTFFont::TTFFont()
     : _initialized(false), _face(), _ttfFile(0), _size(0), _width(0), _height(0), _ascent(0),
-      _descent(0), _glyphs(), _glyphSlots(), _monochrome(false), _hasKerning(false) {
+      _descent(0), _glyphs(), _monochrome(false), _hasKerning(false) {
 }
 
 TTFFont::~TTFFont() {
@@ -214,8 +213,9 @@ bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, bool
 	if (!mapping) {
 		// Load all ISO-8859-1 characters.
 		for (uint i = 0; i < 256; ++i) {
-			if (!cacheGlyph(_glyphs[i], _glyphSlots[i], i))
-				_glyphSlots[i] = 0;
+			if (!cacheGlyph(_glyphs[i], i)) {
+				_glyphs.erase(i);
+			}
 		}
 	} else {
 		for (uint i = 0; i < 256; ++i) {
@@ -223,8 +223,8 @@ bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, bool
 			const bool isRequired = (mapping[i] & 0x80000000) != 0;
 			// Check whether loading an important glyph fails and error out if
 			// that is the case.
-			if (!cacheGlyph(_glyphs[i], _glyphSlots[i], unicode)) {
-				_glyphSlots[i] = 0;
+			if (!cacheGlyph(_glyphs[i], unicode)) {
+				_glyphs.erase(i);
 				if (isRequired)
 					return false;
 			}
@@ -255,12 +255,22 @@ int TTFFont::getKerningOffset(uint32 left, uint32 right) const {
 	if (!_hasKerning)
 		return 0;
 
-	if (left > 255 || right > 255) {
+	FT_UInt leftGlyph, rightGlyph;
+	GlyphCache::const_iterator glyphEntry;
+
+	glyphEntry = _glyphs.find(left);
+	if (glyphEntry != _glyphs.end()) {
+		leftGlyph = glyphEntry->_value.slot;
+	} else {
 		return 0;
 	}
 
-	FT_UInt leftGlyph = _glyphSlots[left];
-	FT_UInt rightGlyph = _glyphSlots[right];
+	glyphEntry = _glyphs.find(right);
+	if (glyphEntry != _glyphs.end()) {
+		rightGlyph = glyphEntry->_value.slot;
+	} else {
+		return 0;
+	}
 
 	if (!leftGlyph || !rightGlyph)
 		return 0;
@@ -380,11 +390,13 @@ void TTFFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) con
 	}
 }
 
-bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) {
-	slot = FT_Get_Char_Index(_face, chr);
+bool TTFFont::cacheGlyph(Glyph &glyph, uint chr) {
+	FT_UInt slot = FT_Get_Char_Index(_face, chr);
 	if (!slot)
 		return false;
 
+	glyph.slot = slot;
+
 	// We use the light target and render mode to improve the looks of the
 	// glyphs. It is most noticable in FreeSansBold.ttf, where otherwise the
 	// 't' glyph looks like it is cut off on the right side.
@@ -460,6 +472,7 @@ bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) {
 
 	default:
 		warning("TTFFont::cacheGlyph: Unsupported pixel mode %d", bitmap.pixel_mode);
+		glyph.image.free();
 		return false;
 	}
 


Commit: 09c634dd555c9ed102f2f583813c4b943235be47
    https://github.com/scummvm/scummvm/commit/09c634dd555c9ed102f2f583813c4b943235be47
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:54-08:00

Commit Message:
GRAPHICS: Allow TTFFont to cache glyphs when required.

This should allow TTFFont to display UTF-32 characters from fonts.

Changed paths:
    graphics/fonts/ttf.cpp



diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp
index 7c48bdf..be3cd94 100644
--- a/graphics/fonts/ttf.cpp
+++ b/graphics/fonts/ttf.cpp
@@ -129,9 +129,11 @@ private:
 		FT_UInt slot;
 	};
 
-	bool cacheGlyph(Glyph &glyph, uint chr);
+	bool cacheGlyph(Glyph &glyph, uint32 chr) const;
 	typedef Common::HashMap<uint32, Glyph> GlyphCache;
-	GlyphCache _glyphs;
+	mutable GlyphCache _glyphs;
+	bool _allowLateCaching;
+	void assureCached(uint32 chr) const;
 
 	bool _monochrome;
 	bool _hasKerning;
@@ -211,6 +213,9 @@ bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, bool
 	_height = _ascent - _descent + 1;
 
 	if (!mapping) {
+		// Allow loading of all unicode characters.
+		_allowLateCaching = true;
+
 		// Load all ISO-8859-1 characters.
 		for (uint i = 0; i < 256; ++i) {
 			if (!cacheGlyph(_glyphs[i], i)) {
@@ -218,6 +223,9 @@ bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, bool
 			}
 		}
 	} else {
+		// We have a fixed map of characters do not load more later.
+		_allowLateCaching = false;
+
 		for (uint i = 0; i < 256; ++i) {
 			const uint32 unicode = mapping[i] & 0x7FFFFFFF;
 			const bool isRequired = (mapping[i] & 0x80000000) != 0;
@@ -244,6 +252,7 @@ int TTFFont::getMaxCharWidth() const {
 }
 
 int TTFFont::getCharWidth(uint32 chr) const {
+	assureCached(chr);
 	GlyphCache::const_iterator glyphEntry = _glyphs.find(chr);
 	if (glyphEntry == _glyphs.end())
 		return 0;
@@ -255,6 +264,9 @@ int TTFFont::getKerningOffset(uint32 left, uint32 right) const {
 	if (!_hasKerning)
 		return 0;
 
+	assureCached(left);
+	assureCached(right);
+
 	FT_UInt leftGlyph, rightGlyph;
 	GlyphCache::const_iterator glyphEntry;
 
@@ -319,6 +331,7 @@ void renderGlyph(uint8 *dstPos, const int dstPitch, const uint8 *srcPos, const i
 } // End of anonymous namespace
 
 void TTFFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+	assureCached(chr);
 	GlyphCache::const_iterator glyphEntry = _glyphs.find(chr);
 	if (glyphEntry == _glyphs.end())
 		return;
@@ -390,7 +403,7 @@ void TTFFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) con
 	}
 }
 
-bool TTFFont::cacheGlyph(Glyph &glyph, uint chr) {
+bool TTFFont::cacheGlyph(Glyph &glyph, uint32 chr) const {
 	FT_UInt slot = FT_Get_Char_Index(_face, chr);
 	if (!slot)
 		return false;
@@ -479,6 +492,17 @@ bool TTFFont::cacheGlyph(Glyph &glyph, uint chr) {
 	return true;
 }
 
+void TTFFont::assureCached(uint32 chr) const {
+	if (!chr || !_allowLateCaching || _glyphs.contains(chr)) {
+		return;
+	}
+
+	Glyph newGlyph;
+	if (cacheGlyph(newGlyph, chr)) {
+		_glyphs[chr] = newGlyph;
+	}
+}
+
 Font *loadTTFFont(Common::SeekableReadStream &stream, int size, uint dpi, bool monochrome, const uint32 *mapping) {
 	TTFFont *font = new TTFFont();
 


Commit: 9da09f584679553098c748f2839a617ed1774e83
    https://github.com/scummvm/scummvm/commit/9da09f584679553098c748f2839a617ed1774e83
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:54-08:00

Commit Message:
GRAPHICS: Allow Font to accept U32String as strings.

Changed paths:
    graphics/font.cpp
    graphics/font.h



diff --git a/graphics/font.cpp b/graphics/font.cpp
index 519d63a..e9f139c 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -30,89 +30,28 @@ int Font::getKerningOffset(uint32 left, uint32 right) const {
 	return 0;
 }
 
-int Font::getStringWidth(const Common::String &str) const {
+namespace {
+
+template<class StringType>
+int getStringWidthImpl(const Font &font, const StringType &str) {
 	int space = 0;
-	uint last = 0;
+	typename StringType::unsigned_type last = 0;
 
 	for (uint i = 0; i < str.size(); ++i) {
-		const uint cur = str[i];
-		space += getCharWidth(cur) + getKerningOffset(last, cur);
+		const typename StringType::unsigned_type cur = str[i];
+		space += font.getCharWidth(cur) + font.getKerningOffset(last, cur);
 		last = cur;
 	}
 
 	return space;
 }
 
-void Font::drawString(Surface *dst, const Common::String &sOld, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+template<class StringType>
+void drawStringImpl(const Font &font, Surface *dst, const StringType &str, int x, int y, int w, uint32 color, TextAlign align, int deltax) {
 	assert(dst != 0);
-	const int leftX = x, rightX = x + w;
-	uint i;
-	Common::String s = sOld;
-	int width = getStringWidth(s);
-	Common::String str;
-
-	if (useEllipsis && width > w && s.hasSuffix("...")) {
-		// String is too wide. Check whether it ends in an ellipsis
-		// ("..."). If so, remove that and try again!
-		s.deleteLastChar();
-		s.deleteLastChar();
-		s.deleteLastChar();
-		width = getStringWidth(s);
-	}
-
-	if (useEllipsis && width > w) {
-		// String is too wide. So we shorten it "intelligently" by
-		// replacing parts of the string by an ellipsis. There are
-		// three possibilities for this: replace the start, the end, or
-		// the middle of the string. What is best really depends on the
-		// context; but unless we want to make this configurable,
-		// replacing the middle seems to be a good compromise.
-
-		const int ellipsisWidth = getStringWidth("...");
-
-		// SLOW algorithm to remove enough of the middle. But it is good enough
-		// for now.
-		const int halfWidth = (w - ellipsisWidth) / 2;
-		int w2 = 0;
-		uint last = 0;
-
-		for (i = 0; i < s.size(); ++i) {
-			const uint cur = s[i];
-			int charWidth = getCharWidth(cur) + getKerningOffset(last, cur);
-			if (w2 + charWidth > halfWidth)
-				break;
-			last = cur;
-			w2 += charWidth;
-			str += cur;
-		}
-
-		// At this point we know that the first 'i' chars are together 'w2'
-		// pixels wide. We took the first i-1, and add "..." to them.
-		str += "...";
-		last = '.';
 
-		// The original string is width wide. Of those we already skipped past
-		// w2 pixels, which means (width - w2) remain.
-		// The new str is (w2+ellipsisWidth) wide, so we can accommodate about
-		// (w - (w2+ellipsisWidth)) more pixels.
-		// Thus we skip ((width - w2) - (w - (w2+ellipsisWidth))) =
-		// (width + ellipsisWidth - w)
-		int skip = width + ellipsisWidth - w;
-		for (; i < s.size() && skip > 0; ++i) {
-			const uint cur = s[i];
-			skip -= getCharWidth(cur) + getKerningOffset(last, cur);
-			last = cur;
-		}
-
-		// Append the remaining chars, if any
-		for (; i < s.size(); ++i) {
-			str += s[i];
-		}
-
-		width = getStringWidth(str);
-	} else {
-		str = s;
-	}
+	const int leftX = x, rightX = x + w;
+	int width = font.getStringWidth(str);
 
 	if (align == kTextAlignCenter)
 		x = x + (w - width)/2;
@@ -120,29 +59,29 @@ void Font::drawString(Surface *dst, const Common::String &sOld, int x, int y, in
 		x = x + w - width;
 	x += deltax;
 
-	uint last = 0;
-	for (i = 0; i < str.size(); ++i) {
-		const uint cur = str[i];
-		x += getKerningOffset(last, cur);
+	typename StringType::unsigned_type last = 0;
+	for (typename StringType::const_iterator i = str.begin(), end = str.end(); i != end; ++i) {
+		const typename StringType::unsigned_type cur = *i;
+		x += font.getKerningOffset(last, cur);
 		last = cur;
-		w = getCharWidth(cur);
+		w = font.getCharWidth(cur);
 		if (x+w > rightX)
 			break;
 		if (x+w >= leftX)
-			drawChar(dst, str[i], x, y, color);
+			font.drawChar(dst, cur, x, y, color);
 		x += w;
 	}
 }
 
-
+template<class StringType>
 struct WordWrapper {
-	Common::Array<Common::String> &lines;
+	Common::Array<StringType> &lines;
 	int actualMaxLineWidth;
 
-	WordWrapper(Common::Array<Common::String> &l) : lines(l), actualMaxLineWidth(0) {
+	WordWrapper(Common::Array<StringType> &l) : lines(l), actualMaxLineWidth(0) {
 	}
 
-	void add(Common::String &line, int &w) {
+	void add(StringType &line, int &w) {
 		if (actualMaxLineWidth < w)
 			actualMaxLineWidth = w;
 
@@ -153,10 +92,11 @@ struct WordWrapper {
 	}
 };
 
-int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
-	WordWrapper wrapper(lines);
-	Common::String line;
-	Common::String tmpStr;
+template<class StringType>
+int wordWrapTextImpl(const Font &font, const StringType &str, int maxWidth, Common::Array<StringType> &lines) {
+	WordWrapper<StringType> wrapper(lines);
+	StringType line;
+	StringType tmpStr;
 	int lineWidth = 0;
 	int tmpWidth = 0;
 
@@ -173,10 +113,10 @@ int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Co
 	// of a line. If we encounter such a word, we have to wrap it over multiple
 	// lines.
 
-	uint last = 0;
-	for (Common::String::const_iterator x = str.begin(); x != str.end(); ++x) {
-		const byte c = *x;
-		const int w = getCharWidth(c) + getKerningOffset(last, c);
+	typename StringType::unsigned_type last = 0;
+	for (typename StringType::const_iterator x = str.begin(); x != str.end(); ++x) {
+		const typename StringType::unsigned_type c = *x;
+		const int w = font.getCharWidth(c) + font.getKerningOffset(last, c);
 		last = c;
 		const bool wouldExceedWidth = (lineWidth + tmpWidth + w > maxWidth);
 
@@ -212,7 +152,7 @@ int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Co
 					tmpStr.deleteChar(0);
 					// This is not very fast, but it is the simplest way to
 					// assure we do not mess something up because of kerning.
-					tmpWidth = getStringWidth(tmpStr);
+					tmpWidth = font.getStringWidth(tmpStr);
 				}
 			} else {
 				wrapper.add(tmpStr, tmpWidth);
@@ -232,5 +172,98 @@ int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Co
 	return wrapper.actualMaxLineWidth;
 }
 
+} // End of anonymous namespace
+
+int Font::getStringWidth(const Common::String &str) const {
+	return getStringWidthImpl(*this, str);
+}
+
+int Font::getStringWidth(const Common::U32String &str) const {
+	return getStringWidthImpl(*this, str);
+}
+
+void Font::drawString(Surface *dst, const Common::String &sOld, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+	Common::String s = sOld;
+	int width = getStringWidth(s);
+	Common::String str;
+
+	if (useEllipsis && width > w && s.hasSuffix("...")) {
+		// String is too wide. Check whether it ends in an ellipsis
+		// ("..."). If so, remove that and try again!
+		s.deleteLastChar();
+		s.deleteLastChar();
+		s.deleteLastChar();
+		width = getStringWidth(s);
+	}
+
+	if (useEllipsis && width > w) {
+		// String is too wide. So we shorten it "intelligently" by
+		// replacing parts of the string by an ellipsis. There are
+		// three possibilities for this: replace the start, the end, or
+		// the middle of the string. What is best really depends on the
+		// context; but unless we want to make this configurable,
+		// replacing the middle seems to be a good compromise.
+
+		const int ellipsisWidth = getStringWidth("...");
+
+		// SLOW algorithm to remove enough of the middle. But it is good enough
+		// for now.
+		const int halfWidth = (w - ellipsisWidth) / 2;
+		int w2 = 0;
+		Common::String::unsigned_type last = 0;
+		uint i;
+
+		for (i = 0; i < s.size(); ++i) {
+			const Common::String::unsigned_type cur = s[i];
+			int charWidth = getCharWidth(cur) + getKerningOffset(last, cur);
+			if (w2 + charWidth > halfWidth)
+				break;
+			last = cur;
+			w2 += charWidth;
+			str += cur;
+		}
+
+		// At this point we know that the first 'i' chars are together 'w2'
+		// pixels wide. We took the first i-1, and add "..." to them.
+		str += "...";
+		last = '.';
+
+		// The original string is width wide. Of those we already skipped past
+		// w2 pixels, which means (width - w2) remain.
+		// The new str is (w2+ellipsisWidth) wide, so we can accommodate about
+		// (w - (w2+ellipsisWidth)) more pixels.
+		// Thus we skip ((width - w2) - (w - (w2+ellipsisWidth))) =
+		// (width + ellipsisWidth - w)
+		int skip = width + ellipsisWidth - w;
+		for (; i < s.size() && skip > 0; ++i) {
+			const Common::String::unsigned_type cur = s[i];
+			skip -= getCharWidth(cur) + getKerningOffset(last, cur);
+			last = cur;
+		}
+
+		// Append the remaining chars, if any
+		for (; i < s.size(); ++i) {
+			str += s[i];
+		}
+
+		width = getStringWidth(str);
+	} else {
+		str = s;
+	}
+
+	drawStringImpl(*this, dst, str, x, y, w, color, align, deltax);
+}
+
+void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align) const {
+	drawStringImpl(*this, dst, str, x, y, w, color, align, 0);
+}
+
+int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
+	return wordWrapTextImpl(*this, str, maxWidth, lines);
+}
+
+int Font::wordWrapText(const Common::U32String &str, int maxWidth, Common::Array<Common::U32String> &lines) const {
+	return wordWrapTextImpl(*this, str, maxWidth, lines);
+}
 
 } // End of namespace Graphics
diff --git a/graphics/font.h b/graphics/font.h
index 62538e3..77b7623 100644
--- a/graphics/font.h
+++ b/graphics/font.h
@@ -23,6 +23,7 @@
 #define GRAPHICS_FONT_H
 
 #include "common/str.h"
+#include "common/ustr.h"
 
 namespace Common {
 template<class T> class Array;
@@ -100,11 +101,13 @@ public:
 
 	// TODO: Add doxygen comments to this
 	void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
+	void drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
 
 	/**
 	 * Compute and return the width the string str has when rendered using this font.
 	 */
 	int getStringWidth(const Common::String &str) const;
+	int getStringWidth(const Common::U32String &str) const;
 
 	/**
 	 * Take a text (which may contain newline characters) and word wrap it so that
@@ -120,6 +123,7 @@ public:
 	 * @return the maximal width of any of the lines added to lines
 	 */
 	int wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const;
+	int wordWrapText(const Common::U32String &str, int maxWidth, Common::Array<Common::U32String> &lines) const;
 };
 
 } // End of namespace Graphics


Commit: a6fff7a8054ce84c3482ff7ddc9365fab324200f
    https://github.com/scummvm/scummvm/commit/a6fff7a8054ce84c3482ff7ddc9365fab324200f
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:54-08:00

Commit Message:
WINTERMUTE: Switch WideString to U32String.

Changed paths:
    engines/wintermute/base/font/base_font_truetype.cpp
    engines/wintermute/base/font/base_font_truetype.h
    engines/wintermute/base/scriptables/script_ext_string.cpp
    engines/wintermute/dctypes.h
    engines/wintermute/utils/string_util.cpp
    engines/wintermute/utils/string_util.h



diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index d6f0914..b879e78 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -121,7 +121,7 @@ int BaseFontTT::getTextWidth(const byte *text, int maxLength) {
 	}
 
 	if (maxLength >= 0 && textStr.size() > (uint32)maxLength) {
-		textStr = Common::String(textStr.c_str(), (uint32)maxLength);
+		textStr = WideString(textStr.c_str(), (uint32)maxLength);
 	}
 	//text = text.substr(0, MaxLength); // TODO: Remove
 
@@ -155,19 +155,19 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign
 		return;
 	}
 
-	WideString textStr = (const char *)text;
+	WideString textStr;
 
 	// TODO: Why do we still insist on Widestrings everywhere?
-	/*  if (_gameRef->_textEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text);
-	        else text = StringUtil::AnsiToWide((char *)Text);*/
 	// HACK: J.U.L.I.A. uses CP1252, we need to fix that,
 	// And we still don't have any UTF8-support.
-	if (_gameRef->_textEncoding != TEXT_UTF8) {
+	if (_gameRef->_textEncoding == TEXT_UTF8) {
+		textStr = StringUtil::utf8ToWide((const char *)text);
+	} else {
 		textStr = StringUtil::ansiToWide((const char *)text);
 	}
 
 	if (maxLength >= 0 && textStr.size() > (uint32)maxLength) {
-		textStr = Common::String(textStr.c_str(), (uint32)maxLength);
+		textStr = WideString(textStr.c_str(), (uint32)maxLength);
 	}
 	//text = text.substr(0, MaxLength); // TODO: Remove
 
@@ -248,7 +248,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
 	//TextLineList lines;
 	// TODO: Use WideString-conversion here.
 	//WrapText(text, width, maxHeight, lines);
-	Common::Array<Common::String> lines;
+	Common::Array<WideString> lines;
 	_font->wordWrapText(text, width, lines);
 
 	while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) {
@@ -267,7 +267,8 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
 		alignment = Graphics::kTextAlignRight;
 	}
 
-	debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
+	// TODO: This debug call does not work with WideString because text.c_str() returns an uint32 array.
+	//debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
 //	void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
 	Graphics::Surface *surface = new Graphics::Surface();
 	if (_deletableFont) { // We actually have a TTF
@@ -276,7 +277,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
 		surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
 	}
 	uint32 useColor = 0xffffffff;
-	Common::Array<Common::String>::iterator it;
+	Common::Array<WideString>::iterator it;
 	int heightOffset = 0;
 	for (it = lines.begin(); it != lines.end(); ++it) {
 		_font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment);
@@ -647,9 +648,9 @@ void BaseFontTT::measureText(const WideString &text, int maxWidth, int maxHeight
 	//TextLineList lines;
 
 	if (maxWidth >= 0) {
-		Common::Array<Common::String> lines;
+		Common::Array<WideString> lines;
 		_font->wordWrapText(text, maxWidth, lines);
-		Common::Array<Common::String>::iterator it;
+		Common::Array<WideString>::iterator it;
 		textWidth = 0;
 		for (it = lines.begin(); it != lines.end(); ++it) {
 			textWidth = MAX(textWidth, _font->getStringWidth(*it));
diff --git a/engines/wintermute/base/font/base_font_truetype.h b/engines/wintermute/base/font/base_font_truetype.h
index 7a96cdf..edb41a1 100644
--- a/engines/wintermute/base/font/base_font_truetype.h
+++ b/engines/wintermute/base/font/base_font_truetype.h
@@ -56,9 +56,8 @@ private:
 		bool _marked;
 		uint32 _lastUsed;
 
-		BaseCachedTTFontText() {
+		BaseCachedTTFontText() : _text() {
 			//_text = L"";
-			_text = "";
 			_width = _maxHeight = _maxLength = -1;
 			_align = TAL_LEFT;
 			_surface = nullptr;
diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp
index b6d2844..65bec03 100644
--- a/engines/wintermute/base/scriptables/script_ext_string.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_string.cpp
@@ -298,21 +298,13 @@ bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
 
 		uint32 start = 0;
 		for(uint32 i = 0; i < str.size() + 1; i++) {
-			char ch = str.c_str()[i];
-			if(ch=='\0' || delims.contains(ch))
-			{
-				char *part = new char[i - start + 1];
-				if(i != start) {
-					Common::strlcpy(part, str.c_str() + start, i - start + 1);
-					part[i - start] = '\0';
+			uint32 ch = str[i];
+			if (ch =='\0' || delims.contains(ch)) {
+				if (i != start) {
+					parts.push_back(WideString(str.c_str() + start, i - start + 1));
 				} else {
-					part[0] = '\0';
+					parts.push_back(WideString());
 				}
-				val = new ScValue(_gameRef, part);
-				array->push(val);
-				delete[] part;
-				delete val;
-				val = nullptr;
 				start = i + 1;
 			}
 		}
diff --git a/engines/wintermute/dctypes.h b/engines/wintermute/dctypes.h
index b403221..4371ee4 100644
--- a/engines/wintermute/dctypes.h
+++ b/engines/wintermute/dctypes.h
@@ -31,6 +31,7 @@
 
 
 #include "common/str.h"
+#include "common/ustr.h"
 #include "common/list.h"
 #include "common/array.h"
 
@@ -41,7 +42,7 @@ namespace Wintermute {
 //typedef std::wstring WideString;
 typedef Common::String AnsiString;
 typedef Common::String Utf8String;
-typedef Common::String WideString; // NB: Not actually true I presume.
+typedef Common::U32String WideString;
 
 typedef Common::List<WideString> WideStringList;
 typedef Common::List<AnsiString> AnsiStringList;
diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp
index d5d6c7f..702dd04 100644
--- a/engines/wintermute/utils/string_util.cpp
+++ b/engines/wintermute/utils/string_util.cpp
@@ -48,201 +48,96 @@ bool StringUtil::compareNoCase(const AnsiString &str1, const AnsiString &str2) {
     return (str1lc == str2lc);
 }*/
 
-Common::String StringUtil::substituteUtf8Characters(Common::String &str) {
-	uint strSize = str.size();
-	Common::String punctuation("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");
-
-	if (isAscii(str))
-		return str;
-
-	for (uint32 i = 0; i < strSize; i++) {
-		if (!Common::isAlnum(str[i]) && str[i] != ' ' && !punctuation.contains(str[i])) {
-			// Replace some UTF-8 characters with (almost) equivalent ANSII ones
-			if ((byte)str[i] == 0xc2 && i + 1 < str.size() && (byte)str[i + 1] == 0xa9) {
-				// UTF-8 copyright character, substitute with 'c'
-				str.deleteChar(i);
-				str.setChar('c', i);
-				strSize--;
-			}
-		}
-	}
-
-	return str;
-}
-
-bool StringUtil::isAscii(const Common::String &str) {
-	Common::String punctuation("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");
-
-	for (uint32 i = 0; i < str.size(); i++) {
-		if (!Common::isAlnum(str[i]) && str[i] != ' ' && !punctuation.contains(str[i]))
-			return false;
-	}
-
-	return true;
-}
-
 //////////////////////////////////////////////////////////////////////////
 WideString StringUtil::utf8ToWide(const Utf8String &Utf8Str) {
-	// WORKAROUND: Since wide strings aren't supported yet, we make this function
-	// work at least with ASCII strings. This should cover all English versions.
-	Common::String asciiString = Utf8Str;
-	asciiString = substituteUtf8Characters(asciiString);
-	if (isAscii(asciiString)) {
-		// No special (UTF-8) characters found, just return the string
-		return asciiString;
-	} else {
-		warning("String contains special (UTF-8) characters: '%s'", Utf8Str.c_str());
-	}
-
-	error("StringUtil::Utf8ToWide - WideString not supported yet for UTF-8 characters");
-
-	/*  size_t WideSize = Utf8Str.size();
-
-	    if (sizeof(wchar_t) == 2) {
-	        wchar_t *WideStringNative = new wchar_t[WideSize + 1];
-
-	        const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
-	        const UTF8 *SourceEnd = SourceStart + WideSize;
+	size_t wideSize = Utf8Str.size();
 
-	        UTF16 *TargetStart = reinterpret_cast<UTF16 *>(WideStringNative);
-	        UTF16 *TargetEnd = TargetStart + WideSize + 1;
+	uint32 *wideStringNative = new uint32[wideSize + 1];
 
-	        ConversionResult res = ConvertUTF8toUTF16(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
-	        if (res != conversionOK) {
-	            delete[] WideStringNative;
-	            return L"";
-	        }
-	        *TargetStart = 0;
-	        WideString ResultString(WideStringNative);
-	        delete[] WideStringNative;
+	const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
+	const UTF8 *sourceEnd = sourceStart + wideSize;
 
-	        return ResultString;
-	    } else if (sizeof(wchar_t) == 4) {
-	        wchar_t *WideStringNative = new wchar_t[WideSize + 1];
+	UTF32 *targetStart = reinterpret_cast<UTF32 *>(wideStringNative);
+	UTF32 *targetEnd = targetStart + wideSize;
 
-	        const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
-	        const UTF8 *SourceEnd = SourceStart + WideSize;
-
-	        UTF32 *TargetStart = reinterpret_cast<UTF32 *>(WideStringNative);
-	        UTF32 *TargetEnd = TargetStart + WideSize;
-
-	        ConversionResult res = ConvertUTF8toUTF32(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
-	        if (res != conversionOK) {
-	            delete[] WideStringNative;
-	            return L"";
-	        }
-	        *TargetStart = 0;
-	        WideString ResultString(WideStringNative);
-	        delete[] WideStringNative;
-
-	        return ResultString;
-	    } else {
-	        return L"";
-	    }*/
-	return "";
+	ConversionResult res = ConvertUTF8toUTF32(&sourceStart, sourceEnd, &targetStart, targetEnd, strictConversion);
+	if (res != conversionOK) {
+		delete[] wideStringNative;
+		return WideString();
+	}
+	*targetStart = 0;
+	WideString resultString(wideStringNative);
+	delete[] wideStringNative;
+	return resultString;
 }
 
 //////////////////////////////////////////////////////////////////////////
 Utf8String StringUtil::wideToUtf8(const WideString &WideStr) {
-	// WORKAROUND: Since UTF-8 strings aren't supported yet, we make this function
-	// work at least with ASCII strings. This should cover all English versions.
-	Common::String asciiString = WideStr;
-	asciiString = substituteUtf8Characters(asciiString);
-	if (isAscii(asciiString)) {
-		// No special (UTF-8) characters found, just return the string
-		return asciiString;
-	} else {
-		warning("String contains special (UTF-8) characters: '%s'", WideStr.c_str());
-	}
+	size_t wideSize = WideStr.size();
 
-	error("StringUtil::wideToUtf8 - WideString not supported yet for UTF-8 characters");
-	
-	/*  size_t WideSize = WideStr.length();
+	size_t utf8Size = 4 * wideSize + 1;
+	char *utf8StringNative = new char[utf8Size];
 
-	    if (sizeof(wchar_t) == 2) {
-	        size_t utf8Size = 3 * WideSize + 1;
-	        char *utf8StringNative = new char[Utf8Size];
+	const UTF32 *sourceStart = reinterpret_cast<const UTF32 *>(WideStr.c_str());
+	const UTF32 *sourceEnd = sourceStart + wideSize;
 
-	        const UTF16 *SourceStart = reinterpret_cast<const UTF16 *>(WideStr.c_str());
-	        const UTF16 *SourceEnd = SourceStart + WideSize;
+	UTF8 *targetStart = reinterpret_cast<UTF8 *>(utf8StringNative);
+	UTF8 *targetEnd = targetStart + utf8Size;
 
-	        UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative);
-	        UTF8 *TargetEnd = TargetStart + Utf8Size;
-
-	        ConversionResult res = ConvertUTF16toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
-	        if (res != conversionOK) {
-	            delete[] Utf8StringNative;
-	            return (Utf8String)"";
-	        }
-	        *TargetStart = 0;
-	        Utf8String ResultString(Utf8StringNative);
-	        delete[] Utf8StringNative;
-	        return ResultString;
-	    } else if (sizeof(wchar_t) == 4) {
-	        size_t utf8Size = 4 * WideSize + 1;
-	        char *utf8StringNative = new char[Utf8Size];
-
-	        const UTF32 *SourceStart = reinterpret_cast<const UTF32 *>(WideStr.c_str());
-	        const UTF32 *SourceEnd = SourceStart + WideSize;
-
-	        UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative);
-	        UTF8 *TargetEnd = TargetStart + Utf8Size;
-
-	        ConversionResult res = ConvertUTF32toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
-	        if (res != conversionOK) {
-	            delete[] Utf8StringNative;
-	            return (Utf8String)"";
-	        }
-	        *TargetStart = 0;
-	        Utf8String ResultString(Utf8StringNative);
-	        delete[] Utf8StringNative;
-	        return ResultString;
-	    } else {
-	        return (Utf8String)"";
-	    }*/
-	return "";
+	ConversionResult res = ConvertUTF32toUTF8(&sourceStart, sourceEnd, &targetStart, targetEnd, strictConversion);
+	if (res != conversionOK) {
+		delete[] utf8StringNative;
+		return Utf8String();
+	}
+	*targetStart = 0;
+	Utf8String resultString(utf8StringNative);
+	delete[] utf8StringNative;
+	return resultString;
 }
 
 //////////////////////////////////////////////////////////////////////////
 WideString StringUtil::ansiToWide(const AnsiString &str) {
-	// TODO: This function gets called a lot, so warnings like these drown out the usefull information
-	Common::String converted = "";
-	uint32 index = 0;
-	while (index != str.size()) {
-		byte c = str[index];
-		if (c == 146) {
-			converted += (char)39;  // Replace right-quote with apostrophe
-		} else if (c == 133) {
-			converted += Common::String("..."); // Replace ...-symbol with ...
+	WideString result;
+	for (AnsiString::const_iterator i = str.begin(), end = str.end(); i != end; ++i) {
+		const byte c = *i;
+		if (c < 0x80 || c >= 0xA0) {
+			result += c;
 		} else {
-			converted += c;
+			uint32 utf32 = _ansiToUTF32[c - 0x80];
+			if (utf32) {
+				result += utf32;
+			} else {
+				// It's an invalid CP1252 character...
+			}
 		}
-		index++;
 	}
-	// using default os locale!
-
-	/*  setlocale(LC_CTYPE, "");
-	    size_t wideSize = mbstowcs(NULL, str.c_str(), 0) + 1;
-	    wchar_t *wstr = new wchar_t[WideSize];
-	    mbstowcs(wstr, str.c_str(), WideSize);
-	    WideString ResultString(wstr);
-	    delete[] wstr;
-	    return ResultString;*/
-	return WideString(converted);
+	return result;
 }
 
 //////////////////////////////////////////////////////////////////////////
 AnsiString StringUtil::wideToAnsi(const WideString &wstr) {
-	// using default os locale!
-	// TODO: This function gets called a lot, so warnings like these drown out the usefull information
-	/*  setlocale(LC_CTYPE, "");
-	    size_t wideSize = wcstombs(NULL, wstr.c_str(), 0) + 1;
-	    char *str = new char[WideSize];
-	    wcstombs(str, wstr.c_str(), WideSize);
-	    AnsiString ResultString(str);
-	    delete[] str;
-	    return ResultString;*/
-	return AnsiString(wstr);
+	AnsiString result;
+	for (WideString::const_iterator i = wstr.begin(), end = wstr.end(); i != end; ++i) {
+		const uint32 c = *i;
+		if (c < 0x80 || (c >= 0xA0 && c <= 0xFF)) {
+			result += c;
+		} else {
+			uint32 ansi = 0xFFFFFFFF;
+			for (uint j = 0; j < ARRAYSIZE(_ansiToUTF32); ++j) {
+				if (_ansiToUTF32[j] == c) {
+					ansi = j + 0x80;
+					break;
+				}
+			}
+
+			if (ansi != 0xFFFFFFFF) {
+				result += ansi;
+			} else {
+				// There's no valid CP1252 code for this character...
+			}
+		}
+	}
+	return result;
 }
 
 //////////////////////////////////////////////////////////////////////////
@@ -256,12 +151,7 @@ bool StringUtil::isUtf8BOM(const byte *buffer, uint32 bufferSize) {
 
 //////////////////////////////////////////////////////////////////////////
 int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) {
-	const char *index = strstr(str.c_str(), toFind.c_str());
-	if (index == nullptr) {
-		return -1;
-	} else {
-		return index - str.c_str();
-	}
+	return str.find(toFind, startFrom);
 }
 
 Common::String StringUtil::encodeSetting(const Common::String &str) {
@@ -282,5 +172,10 @@ AnsiString StringUtil::toString(int val) {
 	return Common::String::format("%d", val);
 }
 
+// Mapping of CP1252 characters 0x80...0x9F into UTF-32
+uint32 StringUtil::_ansiToUTF32[32] = {
+	0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
+	0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178
+};
 
 } // End of namespace Wintermute
diff --git a/engines/wintermute/utils/string_util.h b/engines/wintermute/utils/string_util.h
index 05931be..14c40fc 100644
--- a/engines/wintermute/utils/string_util.h
+++ b/engines/wintermute/utils/string_util.h
@@ -37,8 +37,6 @@ class StringUtil {
 public:
 	static bool compareNoCase(const AnsiString &str1, const AnsiString &str2);
 	//static bool compareNoCase(const WideString &str1, const WideString &str2);
-	static bool isAscii(const Common::String &str);
-	static Common::String substituteUtf8Characters(Common::String &str);
 	static WideString utf8ToWide(const Utf8String &Utf8Str);
 	static Utf8String wideToUtf8(const WideString &WideStr);
 	static WideString ansiToWide(const AnsiString &str);
@@ -51,6 +49,9 @@ public:
 	static Common::String decodeSetting(const Common::String &str);
 
 	static AnsiString toString(int val);
+
+private:
+	static uint32 _ansiToUTF32[32];
 };
 
 } // End of namespace Wintermute


Commit: 4c15e51ab540abb4843268921bdd0d27c6e0f9bb
    https://github.com/scummvm/scummvm/commit/4c15e51ab540abb4843268921bdd0d27c6e0f9bb
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:54-08:00

Commit Message:
COMMON: Document U32String a bit better.

Changed paths:
    common/ustr.h



diff --git a/common/ustr.h b/common/ustr.h
index e549c5f..ab9dac7 100644
--- a/common/ustr.h
+++ b/common/ustr.h
@@ -26,6 +26,18 @@
 
 namespace Common {
 
+/**
+ * Very simple string class for UTF-32 strings in ScummVM. The main intention
+ * behind this class is to feature a simple way of displaying UTF-32 strings
+ * through the Graphics::Font API.
+ *
+ * Please note that operations like equals, deleteCharacter, toUppercase, etc.
+ * are only very simplified convenience operations. They might not fully work
+ * as you would expect for a proper UTF-32 string class.
+ *
+ * The presence of \0 characters in the string will cause undefined
+ * behavior in some operations.
+ */
 class U32String {
 public:
 	static const uint32 npos = 0xFFFFFFFF;
@@ -72,14 +84,19 @@ private:
 	}
 
 public:
+	/** Construct a new empty string. */
 	U32String() : _size(0), _str(_storage) { _storage[0] = 0; }
 
+	/** Construct a new string from the given NULL-terminated C string. */
 	explicit U32String(const value_type *str);
 
+	/** Construct a new string containing exactly len characters read from address str. */
 	U32String(const value_type *str, uint32 len);
 
+	/** Construct a new string containing the characters between beginP (including) and endP (excluding). */
 	U32String(const value_type *beginP, const value_type *endP);
 
+	/** Construct a copy of the given string. */
 	U32String(const U32String &str);
 
 	~U32String();
@@ -88,8 +105,16 @@ public:
 	U32String &operator+=(const U32String &str);
 	U32String &operator+=(value_type c);
 
+	/**
+	 * Equivalence comparison operator.
+	 * @see equals
+	 */
 	bool operator==(const U32String &x) const { return equals(x); }
 
+	/**
+	 * Compares whether two U32String are the same based on memory comparison.
+	 * This does *not* do comparison based on canonical equivalence.
+	 */
 	bool equals(const U32String &x) const;
 
 	bool contains(value_type x) const;
@@ -104,16 +129,30 @@ public:
 		return _str[idx];
 	}
 
-	/** Remove the character at position p from the string. */
+	/**
+	 * Removes the value at position p from the string.
+	 * Using this on decomposed characters will not remove the whole
+	 * character!
+	 */
 	void deleteChar(uint32 p);
 
 	/** Clears the string, making it empty. */
 	void clear();
 
-	/** Convert all characters in the string to lowercase. */
+	/**
+	 * Convert all characters in the string to lowercase.
+	 *
+	 * Be aware that this only affects the case of ASCII characters. All
+	 * other characters will not be touched at all.
+	 */
 	void toLowercase();
 
-	/** Convert all characters in the string to uppercase. */
+	/**
+	 * Convert all characters in the string to uppercase.
+	 *
+	 * Be aware that this only affects the case of ASCII characters. All
+	 * other characters will not be touched at all.
+	 */
 	void toUppercase();
 
 	uint32 find(const U32String &str, uint32 pos = 0) const;


Commit: abe6d30f36cdfaef3c7ce7a5c8a48f4d4986d718
    https://github.com/scummvm/scummvm/commit/abe6d30f36cdfaef3c7ce7a5c8a48f4d4986d718
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-11-23T12:34:55-08:00

Commit Message:
COMMON: Document Common::String::unsigned_type.

Changed paths:
    common/str.h



diff --git a/common/str.h b/common/str.h
index 2ad2626..ea2db1d 100644
--- a/common/str.h
+++ b/common/str.h
@@ -235,6 +235,11 @@ public:
 
 public:
 	typedef char          value_type;
+	/**
+	 * Unsigned version of the underlying type. This can be used to cast
+	 * individual string characters to bigger integer types without sign
+	 * extension happening.
+	 */
 	typedef unsigned char unsigned_type;
 	typedef char *        iterator;
 	typedef const char *  const_iterator;


Commit: e718719f918a4941fd72d3b245922a834bc5a5d2
    https://github.com/scummvm/scummvm/commit/e718719f918a4941fd72d3b245922a834bc5a5d2
Author: Johannes Schickel (lordhoto at gmail.com)
Date: 2013-11-26T02:24:03-08:00

Commit Message:
Merge pull request #411 from lordhoto/unicode

Add UTF-32 support to Graphics::Font and Wintermute.

Changed paths:
  A common/ustr.cpp
  A common/ustr.h
    common/module.mk
    common/str.h
    engines/groovie/font.cpp
    engines/groovie/font.h
    engines/wintermute/base/font/base_font_truetype.cpp
    engines/wintermute/base/font/base_font_truetype.h
    engines/wintermute/base/scriptables/script_ext_string.cpp
    engines/wintermute/dctypes.h
    engines/wintermute/utils/string_util.cpp
    engines/wintermute/utils/string_util.h
    graphics/font.cpp
    graphics/font.h
    graphics/fonts/bdf.cpp
    graphics/fonts/bdf.h
    graphics/fonts/ttf.cpp
    graphics/fonts/winfont.cpp
    graphics/fonts/winfont.h









More information about the Scummvm-git-logs mailing list