String.padEnd(length: Int) and multi code point characters

I’ve noticed that String.padEnd() counts multi code point characters (e.g. some emoji) as multiple characters which leads to poor layout with fixed width fonts when padding.

Is this a known issue, or is there a workaround?

thanks,

Daniel

I’m guessing your on the JVM. This is a problem with the java String implementation. While it has no problems saving multi codepoint characters many of the utility functions don’t handle them correctly.
I’m not sure about how complicated it would be to provide an alternate implementation.
The problem is that the java String class represents characters as UTF-16 characters. This means any unicode character that is represented by more than 16 bits is saved as 2 separate Char values. This fact is ignored by many of the functions within String, eg. String.lenght does not return the number of unicode characters, it returns the number of 16bit characters within the String, some emoji counting for 2 characters. If your string also contains invisible characters like the unicode characters responsible for emoji skin color String.lenght might count a single displayed character as having a length of 4 or in some other combinations as even longer.
There was an iPhone bug with a similar problem in 2015 that lead to your phone crashing when you recieved a special arabic text:

I don’t know of any workaround. It probably requires a complete reimplementation of String using a completely different memory system. Chars aren’t the best for manipulating strings outside of plain text. Maybe not use emoji :stuck_out_tongue_winking_eye:

well I’m new to the JVM and Android development, coming from iOS, and I now understand why Android Studio has such a hard time with emoji :weary:. By pushing all the complexity of non-plain text to clients, we as users, get a reading experience that is significantly worse than on native Mac/iOS apps. I understand that there is android.icu.text and com.ibm.icu.text but String is ubiquitous. Even if we adopt these libraries, unit testing on Android is hard as the JVM throws Unimplemented Stub! exceptions.

I honestly believe that kotlin has an opportunity to fix these poor user experiences. Perhaps an opt in compiler plugin that contains a correct default implementation of kotlin.lang.String and requires a conversion with .toJavaString() / .fromJavaString().

Would the community comment on whether an issue on https://github.com/JetBrains/kotlin would be worthwhile? Perhaps by 2022 we could have a uniform text experience in Android Studio and Android.

The right place for issues is https://kotl.in/issue
That said this will probably require a KEEP: https://github.com/Kotlin/KEEP/

I’d be all for it, but this is something that will take a lot of work. My guess if we want something like this we would first need a KEEP as well as a prototype implementation of the String class. At that point it wouldn’t be to hard to implement a compiler plugin to incorporate literals or add this to the language directly.

1 Like