Replace icu::UnicodeString with ICU C API and std::u16string
When sfntly depends on ICU4C a shared library, the shared
library may not provide stable C++ ABI. Use ICU C API instead.
diff --git a/cpp/src/sample/chromium/subsetter_impl.cc b/cpp/src/sample/chromium/subsetter_impl.cc
index 37df212..533c1a0 100644
--- a/cpp/src/sample/chromium/subsetter_impl.cc
+++ b/cpp/src/sample/chromium/subsetter_impl.cc
@@ -23,8 +23,9 @@
#include <limits>
#include <map>
#include <set>
+#include <string>
-#include <unicode/unistr.h>
+#include <unicode/ustring.h>
#include <unicode/uversion.h>
#include "sfntly/table/bitmap/eblc_table.h"
@@ -41,10 +42,6 @@
#include "sfntly/port/memory_input_stream.h"
#include "sfntly/port/memory_output_stream.h"
-#if defined U_USING_ICU_NAMESPACE
- U_NAMESPACE_USE
-#endif
-
namespace {
using namespace sfntly;
@@ -52,7 +49,7 @@
// The bitmap tables must be greater than 16KB to trigger bitmap subsetter.
static const int BITMAP_SIZE_THRESHOLD = 16384;
-void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) {
+void ConstructName(UChar* name_part, std::u16string* name, int32_t name_id) {
switch (name_id) {
case NameId::kFullFontName:
*name = name_part;
@@ -60,7 +57,7 @@
case NameId::kFontFamilyName:
case NameId::kPreferredFamily:
case NameId::kWWSFamilyName: {
- UnicodeString original = *name;
+ std::u16string original = *name;
*name = name_part;
*name += original;
break;
@@ -77,6 +74,38 @@
}
}
+// Convert UTF-8 string into UTF-16 string.
+//
+// Ill-formed input is replaced with U+FFFD.
+// Otherwise, return empty string if other error occurs during the conversion.
+std::u16string ConvertFromUtf8(const char* src) {
+ int32_t srcLength = strlen(src);
+ int32_t destCapacity = srcLength + 1;
+ UChar* buffer = new UChar[destCapacity];
+ std::u16string dest;
+ if (buffer == NULL) {
+ return dest;
+ }
+ int32_t destLength;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ u_strFromUTF8WithSub(buffer, destCapacity, &destLength, src, srcLength,
+ 0xfffd, // Unicode replacement character
+ NULL,
+ &errorCode);
+ if (U_SUCCESS(errorCode)) {
+ dest.append(buffer, destLength);
+ }
+ delete[] buffer;
+ return dest;
+}
+
+int32_t CaseCompareUtf16(const std::u16string& str1,
+ const std::u16string& str2, uint32_t option) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ return u_strCaseCompare(str1.c_str(), str1.length(), str2.c_str(),
+ str2.length(), option, &errorCode);
+}
+
int32_t HashCode(int32_t platform_id, int32_t encoding_id, int32_t language_id,
int32_t name_id) {
int32_t result = platform_id << 24 | encoding_id << 16 | language_id << 8;
@@ -93,14 +122,14 @@
}
bool HasName(const char* font_name, Font* font) {
- UnicodeString font_string = UnicodeString::fromUTF8(font_name);
- if (font_string.isEmpty())
+ std::u16string font_string = ConvertFromUtf8(font_name);
+ if (font_string.empty())
return false;
- UnicodeString regular_suffix = UnicodeString::fromUTF8(" Regular");
- UnicodeString alt_font_string = font_string;
+ std::u16string regular_suffix(u" Regular");
+ std::u16string alt_font_string = font_string;
alt_font_string += regular_suffix;
- typedef std::map<int32_t, UnicodeString> NameMap;
+ typedef std::map<int32_t, std::u16string> NameMap;
NameMap names;
NameTablePtr name_table = down_cast<NameTable*>(font->GetTable(Tag::name));
if (name_table == NULL) {
@@ -135,8 +164,8 @@
if (!names.empty()) {
for (NameMap::iterator i = names.begin(), e = names.end(); i != e; ++i) {
- if (i->second.caseCompare(font_string, 0) == 0 ||
- i->second.caseCompare(alt_font_string, 0) == 0) {
+ if (CaseCompareUtf16(i->second, font_string, 0) == 0 ||
+ CaseCompareUtf16(i->second, alt_font_string, 0) == 0) {
return true;
}
}