Reland "Removing ICU dependencies from skparagraph BUILD.gn file"

This reverts commit 05ce2817f2a060caf8acd5be25b4f29875d63049.

Reason for revert: Fixing the build

Original change's description:
> Revert "Removing ICU dependencies from skparagraph BUILD.gn file"
>
> This reverts commit f1711adb1a04595eba1e9984976bfb92d41d0035.
>
> Reason for revert: Build break
>
> Original change's description:
> > Removing ICU dependencies from skparagraph BUILD.gn file
> >
> > (and from the sources, too)
> >
> > Change-Id: I9d8ff51c91aad4b770b1f183c04734d31252b851
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313148
> > Commit-Queue: Julia Lavrova <jlavrova@google.com>
> > Reviewed-by: Ben Wagner <bungeman@google.com>
>
> TBR=bungeman@google.com,jlavrova@google.com
>
> Change-Id: I1fce2436855e3e2a4cb7d1d7204b3ae49fd530e8
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/314540
> Reviewed-by: Julia Lavrova <jlavrova@google.com>
> Commit-Queue: Julia Lavrova <jlavrova@google.com>

TBR=bungeman@google.com,jlavrova@google.com

Change-Id: I13d78d75698df47930adc2514d1328abc556a209
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/316444
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
diff --git a/modules/skshaper/src/SkUnicode_icu.cpp b/modules/skshaper/src/SkUnicode_icu.cpp
index 1a859fe..13de14d 100644
--- a/modules/skshaper/src/SkUnicode_icu.cpp
+++ b/modules/skshaper/src/SkUnicode_icu.cpp
@@ -4,17 +4,23 @@
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
+#include "include/core/SkString.h"
 #include "include/private/SkTFitsIn.h"
 #include "include/private/SkTemplates.h"
 #include "modules/skshaper/src/SkUnicode.h"
 #include "src/utils/SkUTF.h"
 #include <unicode/ubidi.h>
 #include <unicode/ubrk.h>
+#include <unicode/ustring.h>
 #include <unicode/utext.h>
 #include <unicode/utypes.h>
 #include <vector>
 #include <functional>
 
+#if defined(SK_USING_THIRD_PARTY_ICU)
+#include "SkLoadICU.h"
+#endif
+
 using SkUnicodeBidi = std::unique_ptr<UBiDi, SkFunctionWrapper<decltype(ubidi_close), ubidi_close>>;
 using ICUUText = std::unique_ptr<UText, SkFunctionWrapper<decltype(utext_close), utext_close>>;
 using ICUBreakIterator = std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>>;
@@ -125,23 +131,11 @@
         }
     }
 
-    static int convertUtf8ToUtf16(const char* utf8, size_t utf8Units, std::unique_ptr<uint16_t[]>* utf16) {
-        int utf16Units = SkUTF::UTF8ToUTF16(nullptr, 0, utf8, utf8Units);
-        if (utf16Units < 0) {
-            SkDEBUGF("Convert error: Invalid utf8 input");
-            return utf16Units;
-        }
-        *utf16 = std::unique_ptr<uint16_t[]>(new uint16_t[utf16Units]);
-        SkDEBUGCODE(int dstLen =) SkUTF::UTF8ToUTF16(utf16->get(), utf16Units, utf8, utf8Units);
-        SkASSERT(dstLen == utf16Units);
-        return utf16Units;
-    }
-
     static bool extractBidi(const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* bidiRegions) {
 
         // Convert to UTF16 since for now bidi iterator only operates on utf16
         std::unique_ptr<uint16_t[]> utf16;
-        auto utf16Units = convertUtf8ToUtf16(utf8, utf8Units, &utf16);
+        auto utf16Units = utf8ToUtf16(utf8, utf8Units, &utf16);
         if (utf16Units < 0) {
             return false;
         }
@@ -276,6 +270,29 @@
         return true;
     }
 
+    static int utf8ToUtf16(const char* utf8, size_t utf8Units, std::unique_ptr<uint16_t[]>* utf16) {
+        int utf16Units = SkUTF::UTF8ToUTF16(nullptr, 0, utf8, utf8Units);
+        if (utf16Units < 0) {
+            SkDEBUGF("Convert error: Invalid utf8 input");
+            return utf16Units;
+        }
+        *utf16 = std::unique_ptr<uint16_t[]>(new uint16_t[utf16Units]);
+        SkDEBUGCODE(int dstLen =) SkUTF::UTF8ToUTF16(utf16->get(), utf16Units, utf8, utf8Units);
+        SkASSERT(dstLen == utf16Units);
+        return utf16Units;
+   }
+
+    static int utf16ToUtf8(const uint16_t* utf16, size_t utf16Units, std::unique_ptr<char[]>* utf8) {
+        int utf8Units = SkUTF::UTF16ToUTF8(nullptr, 0, utf16, utf16Units);
+        if (utf8Units < 0) {
+            SkDEBUGF("Convert error: Invalid utf16 input");
+            return utf8Units;
+        }
+        *utf8 = std::unique_ptr<char[]>(new char[utf8Units]);
+        SkDEBUGCODE(int dstLen =) SkUTF::UTF16ToUTF8(utf8->get(), utf8Units, utf16, utf16Units);
+        SkASSERT(dstLen == utf8Units);
+        return utf8Units;
+   }
 public:
     ~SkUnicode_icu() override { }
     std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t text[], int count,
@@ -287,6 +304,25 @@
         return SkBidiIterator_icu::makeBidiIterator(text, count, dir);
     }
 
+    // TODO: Use ICU data file to detect controls and whitespaces
+    bool isControl(SkUnichar utf8) override {
+        return u_iscntrl(utf8);
+    }
+
+    bool isWhitespace(SkUnichar utf8) override {
+        return u_isWhitespace(utf8);
+    }
+
+    SkString convertUtf16ToUtf8(const std::u16string& utf16) override {
+        std::unique_ptr<char[]> utf8;
+        auto utf8Units = SkUnicode_icu::utf16ToUtf8((uint16_t*)utf16.data(), utf16.size(), &utf8);
+        if (utf8Units >= 0) {
+            return SkString(utf8.get(), utf8Units);
+        } else {
+            return SkString();
+        }
+    }
+
     bool getBidiRegions(const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* results) override {
         return extractBidi(utf8, utf8Units, dir, results);
     }
@@ -305,7 +341,7 @@
 
         // Convert to UTF16 since we want the results in utf16
         std::unique_ptr<uint16_t[]> utf16;
-        auto utf16Units = convertUtf8ToUtf16(utf8, utf8Units, &utf16);
+        auto utf16Units = utf8ToUtf16(utf8, utf8Units, &utf16);
         if (utf16Units < 0) {
             return false;
         }
@@ -330,4 +366,12 @@
     }
 };
 
-std::unique_ptr<SkUnicode> SkUnicode::Make() { return std::make_unique<SkUnicode_icu>(); }
+std::unique_ptr<SkUnicode> SkUnicode::Make() {
+    #if defined(SK_USING_THIRD_PARTY_ICU)
+    if (!SkLoadICU()) {
+        SkDEBUGF("SkLoadICU() failed!\n");
+        return nullptr;
+    }
+    #endif
+    return std::make_unique<SkUnicode_icu>();
+}