// We have just transitioned from a word to
// whitespace. See if we have enough space to add
// the word to the line.
- if (word.length() + line.length() > n) {
+ if (width(word.toString()) + width(line.toString()) > n) {
// This word will exceed the line length. Wrap
// at it instead.
result.add(line.toString());
line = new StringBuilder();
}
if ((word.toString().startsWith(" "))
- && (line.length() == 0)
+ && (width(line.toString()) == 0)
) {
line.append(word.substring(1));
} else {
}
} // for (int j = 0; j < rawLines[i].length(); j++)
- if (word.length() + line.length() > n) {
+ if (width(word.toString()) + width(line.toString()) > n) {
// This word will exceed the line length. Wrap at it
// instead.
result.add(line.toString());
line = new StringBuilder();
}
if ((word.toString().startsWith(" "))
- && (line.length() == 0)
+ && (width(line.toString()) == 0)
) {
line.append(word.substring(1));
} else {
List<String> lines = left(str, n);
for (String line: lines) {
StringBuilder sb = new StringBuilder();
- for (int i = 0; i < n - line.length(); i++) {
+ for (int i = 0; i < n - width(line); i++) {
sb.append(' ');
}
sb.append(line);
List<String> lines = left(str, n);
for (String line: lines) {
StringBuilder sb = new StringBuilder();
- int l = (n - line.length()) / 2;
- int r = n - line.length() - l;
+ int l = (n - width(line)) / 2;
+ int r = n - width(line) - l;
for (int i = 0; i < l; i++) {
sb.append(' ');
}
|| ((ch >= 0xffe0) && (ch <= 0xffe6))
|| ((ch >= 0x20000) && (ch <= 0x2fffd))
|| ((ch >= 0x30000) && (ch <= 0x3fffd))
- // TODO: emoji / twemoji
+ // emoji
+ || ((ch >= 0x1f004) && (ch <= 0x1fffd))
)
) {
return 2;
*/
public static int width(final String str) {
int n = 0;
- for (int i = 0; i < str.length(); i++) {
- n += width(str.charAt(i));
+ for (int i = 0; i < str.length();) {
+ int ch = str.codePointAt(i);
+ n += width(ch);
+ i += Character.charCount(ch);
}
return n;
}
+ /**
+ * Check if character is in the CJK range.
+ *
+ * @param ch character to check
+ * @return true if this character is in the CJK range
+ */
+ public static boolean isCjk(final int ch) {
+ return ((ch >= 0x2e80) && (ch <= 0x9fff));
+ }
+
+ /**
+ * Check if character is in the emoji range.
+ *
+ * @param ch character to check
+ * @return true if this character is in the emoji range
+ */
+ public static boolean isEmoji(final int ch) {
+ return ((ch >= 0x1f004) && (ch <= 0x1fffd));
+ }
+
}