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;
       }
     }