Merge "ImageGenerator: switch to BreakIterator from icu library"
diff --git a/tools/image_generator/Android.bp b/tools/image_generator/Android.bp
index ce6e277..2afdd5a 100644
--- a/tools/image_generator/Android.bp
+++ b/tools/image_generator/Android.bp
@@ -19,6 +19,7 @@
 
     static_libs: [
         "commons-cli-1.2",
+        "icu4j-host",
     ],
 
     srcs: [
diff --git a/tools/image_generator/ImageGenerator.java b/tools/image_generator/ImageGenerator.java
index 9d88267..19d187d 100644
--- a/tools/image_generator/ImageGenerator.java
+++ b/tools/image_generator/ImageGenerator.java
@@ -16,6 +16,8 @@
 
 package com.android.recovery.tools;
 
+import com.ibm.icu.text.BreakIterator;
+
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.GnuParser;
 import org.apache.commons.cli.HelpFormatter;
@@ -44,7 +46,6 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
-import java.util.StringTokenizer;
 import java.util.TreeMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -153,22 +154,6 @@
                 }
             };
 
-    // Languages that breaks on arbitrary characters.
-    // TODO(xunchang) switch to icu library if possible. For example, for Thai and Khmer, there is
-    // no space between words; and word breaking is based on grammatical analysis and on word
-    // matching in dictionaries.
-    private static final Set<String> LOGOGRAM_LANGUAGE =
-            new HashSet<String>() {
-                {
-                    add("ja"); // Japanese
-                    add("km"); // Khmer
-                    add("ko"); // Korean
-                    add("lo"); // Lao
-                    add("th"); // Thai
-                    add("zh"); // Chinese
-                }
-            };
-
     /** Exception to indicate the failure to find the translated text strings. */
     public static class LocalizedStringNotFoundException extends Exception {
         public LocalizedStringNotFoundException(String message) {
@@ -408,16 +393,28 @@
                 "Can not find the font file " + fontName + " for language " + language);
     }
 
-    /** Separates the text string by spaces and wraps it by words. */
-    private WrappedTextInfo wrapTextByWords(String text, FontMetrics metrics) {
+    /**
+     * Wraps the text with a maximum of mImageWidth pixels per line.
+     *
+     * @param text the string representation of text to wrap
+     * @param metrics the metrics of the Font used to draw the text; it gives the width in pixels of
+     *     the text given its string representation
+     * @return a WrappedTextInfo class with the width of each AttributedString smaller than
+     *     mImageWidth pixels
+     */
+    private WrappedTextInfo wrapText(String text, FontMetrics metrics) {
         WrappedTextInfo info = new WrappedTextInfo();
-        StringTokenizer st = new StringTokenizer(text, " \n");
+
+        BreakIterator lineBoundary = BreakIterator.getLineInstance();
+        lineBoundary.setText(text);
 
         int lineWidth = 0;  // Width of the processed words of the current line.
+        int start = lineBoundary.first();
         StringBuilder line = new StringBuilder();
-        while (st.hasMoreTokens()) {
-            String token = st.nextToken();
-            int tokenWidth = metrics.stringWidth(token + " ");
+        for (int end = lineBoundary.next(); end != BreakIterator.DONE;
+                start = end, end = lineBoundary.next()) {
+            String token = text.substring(start, end);
+            int tokenWidth = metrics.stringWidth(token);
             // Handles the width mismatch of the word "Android" between different fonts.
             if (token.contains(ANDROID_STRING)
                     && metrics.getFont().canDisplayUpTo(ANDROID_STRING) != -1) {
@@ -430,7 +427,7 @@
                 line = new StringBuilder();
                 lineWidth = 0;
             }
-            line.append(token).append(" ");
+            line.append(token);
             lineWidth += tokenWidth;
         }
 
@@ -439,42 +436,6 @@
         return info;
     }
 
-    /** One character is a word for CJK. */
-    private WrappedTextInfo wrapTextByCharacters(String text, FontMetrics metrics) {
-        WrappedTextInfo info = new WrappedTextInfo();
-        // TODO (xunchang) handle the text wrapping with logogram language mixed with latin.
-        StringBuilder line = new StringBuilder();
-        for (char token : text.toCharArray()) {
-            if (metrics.stringWidth(line + Character.toString(token)) > mImageWidth) {
-                info.addLine(line.toString(), metrics.stringWidth(line.toString()),
-                        metrics.getFont(), null);
-                line = new StringBuilder();
-            }
-            line.append(token);
-        }
-        info.addLine(line.toString(), metrics.stringWidth(line.toString()), metrics.getFont(),
-                null);
-
-        return info;
-    }
-
-    /**
-     * Wraps the text with a maximum of mImageWidth pixels per line.
-     *
-     * @param text the string representation of text to wrap
-     * @param metrics the metrics of the Font used to draw the text; it gives the width in pixels of
-     *     the text given its string representation
-     * @return a WrappedTextInfo class with the width of each AttributedString smaller than
-     *     mImageWidth pixels
-     */
-    private WrappedTextInfo wrapText(String text, FontMetrics metrics, String language) {
-        if (LOGOGRAM_LANGUAGE.contains(language)) {
-            return wrapTextByCharacters(text, metrics);
-        }
-
-        return wrapTextByWords(text, metrics);
-    }
-
     /**
      * Encodes the information of the text image for |locale|. According to minui/resources.cpp, the
      * width, height and locale of the image is decoded as: int w = (row[1] << 8) | row[0]; int h =
@@ -516,7 +477,7 @@
             throws IOException, FontFormatException {
         Graphics2D graphics = createGraphics(locale);
         FontMetrics fontMetrics = graphics.getFontMetrics();
-        WrappedTextInfo wrappedTextInfo = wrapText(text, fontMetrics, locale.getLanguage());
+        WrappedTextInfo wrappedTextInfo = wrapText(text, fontMetrics);
 
         int textWidth = 0;
         for (WrappedTextInfo.LineInfo lineInfo : wrappedTextInfo.mWrappedLines) {
@@ -551,7 +512,7 @@
 
         Graphics2D graphics = createGraphics(locale);
         FontMetrics fontMetrics = graphics.getFontMetrics();
-        WrappedTextInfo wrappedTextInfo = wrapText(text, fontMetrics, locale.getLanguage());
+        WrappedTextInfo wrappedTextInfo = wrapText(text, fontMetrics);
 
         // Marks the start y offset for the text image of current locale; and reserves one line to
         // encode the image metadata.