From acacc9d30f78ae54f689c7257a7c1d38ccb16623 Mon Sep 17 00:00:00 2001 From: xunchang Date: Mon, 26 Nov 2018 15:01:39 -0800 Subject: ImageGenerator: switch to BreakIterator from icu library The icu library takes care of the line boundary, so that we don't need to worry about if the given language is logogram. Bug: 74397117 Test: Generate and check the image Change-Id: I1447f51b178c0fca83c5497d2f5b8e4009ca7f64 --- tools/image_generator/Android.bp | 1 + tools/image_generator/ImageGenerator.java | 85 +++++++++---------------------- 2 files changed, 24 insertions(+), 62 deletions(-) diff --git a/tools/image_generator/Android.bp b/tools/image_generator/Android.bp index ce6e277bc..2afdd5a84 100644 --- a/tools/image_generator/Android.bp +++ b/tools/image_generator/Android.bp @@ -19,6 +19,7 @@ java_library_host { static_libs: [ "commons-cli-1.2", + "icu4j-host", ], srcs: [ diff --git a/tools/image_generator/ImageGenerator.java b/tools/image_generator/ImageGenerator.java index 9d882678a..19d187d24 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.List; 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 @@ public class ImageGenerator { } }; - // 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 LOGOGRAM_LANGUAGE = - new HashSet() { - { - 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 @@ public class ImageGenerator { "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 @@ public class ImageGenerator { line = new StringBuilder(); lineWidth = 0; } - line.append(token).append(" "); + line.append(token); lineWidth += tokenWidth; } @@ -439,42 +436,6 @@ public class ImageGenerator { 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 @@ public class ImageGenerator { 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 @@ public class ImageGenerator { 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. -- cgit v1.2.3