font - Planos suplementarios Unicode en JavaFX
font javafx (1)
TL; DR: Evidentemente JavaFX tiene errores.
Aquí está el texto que estás usando.
🂡𫞂ಠ😀ñ
Representación del punto de código decimal:
127137 178050 3232 128512 241
Representación hexagonal:
0x1F0A1 0x2B782 0xCA0 0x1F600 0xF1
Mostrar error
Java usa UTF-16 internamente. Así que considere la representación UTF-16:
Representación UTF-16:
D83C DCA1 D86D DF82 0CA0 D83D DE00 00F1
Podemos ver que la pantalla muestra los cinco caracteres que espera, pero luego tres caracteres basura.
Entonces, claramente está tratando de mostrar 8 glifos, donde solo hay cinco. Esto es casi seguro porque el código de visualización cuenta 8 caracteres, porque tres caracteres están codificados en UTF-16 como pares de sustitución, así que tome dos palabras de 16 bits cada una. En otras palabras, está utilizando el valor incorrecto para la longitud de la cadena en presencia de pares de sustitución.
Error de texto pegado
UTF-8 Representación de datos de prueba:
F0 9F 82 A1 F0 AB 9E 82 E0 B2 A0 F0 9F 98 80 C3 B1
Lo que se ve es
00F0 ð LATIN SMALL LETTER ETH
009F <control> = APC = APPLICATION PROGRAM COMMAND
0082 <control> = BPH = BREAK PERMITTED HERE
00A1 ¡ INVERTED EXCLAMATION MARK
00F0 ð LATIN SMALL LETTER ETH
(Los dos caracteres de control pueden tener glifos en algunas fuentes que contienen abreviaturas o códigos hexadecimales, que son visibles en su ejemplo).
Representación de hexagonal Latin1:
F0 9F 82 A1 F0
Tenga en cuenta que estos cinco bytes son los mismos que los primeros cinco bytes de la representación UTF-8 del texto previsto.
Conclusión: los datos pegados se han pegado como 5 puntos de código UTF-8 que ocupan 17 bytes, pero se han interpretado como 5 puntos de código Latin1 que ocupan 5 bytes. Nuevamente, se ha usado la propiedad incorrecta para la longitud.
Tengo problemas para tratar con caracteres Unicode desde planos suplementarios ("astrales") en JavaFX. Específicamente, no puedo pegar dichos caracteres en un TextInputDialog
(obtengo algunos caracteres extraños, como ð
), y no puedo usarlos en un WebView (se representan como ).
Los mismos caracteres funcionan perfectamente bien si los ingreso a través de JOptionPane.showInputDialog
y los JOptionPane.showInputDialog
en la consola. Incluso se muestran en una Alert
JavaFX, aunque agrega algo de basura al final.
¿Hay alguna manera de solucionar estos problemas?
Estoy utilizando Oracle JDK versión 1.8.0_51 en Linux.
Ejemplos de caracteres planos suplementarios: 😀 𐂃 🂡 𫞂 𫞂
Si no puede verlos, puede necesitar instalar fuentes adicionales como Symbola o Noto.
Aquí hay un programa de ejemplo (usando una Label
lugar de una vista WebView
):
import javax.swing.JOptionPane;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class UniTest extends Application {
@Override
public void start(final Stage stage) throws Exception {
final String s = new String(new int[]{127137, 178050, 3232, 128512, 241}, 0, 5);
System.out.println("The string: " + s);
System.out.println("Characters: " + s.length());
System.out.println("Code points: " + s.codePoints().count());
JOptionPane.showMessageDialog(null, s, "JOptionPane", JOptionPane.INFORMATION_MESSAGE);
final Alert al = new Alert(AlertType.INFORMATION);
al.setTitle("Alert");
al.setContentText(s);
al.showAndWait();
final TextInputDialog dlg = new TextInputDialog();
dlg.setTitle("TextInputDialog");
dlg.setContentText("Try to paste the string in here");
dlg.showAndWait().ifPresent(x -> System.out.println("Your input: " + x));
final StackPane root = new StackPane();
root.getChildren().add(new Label(s));
stage.setScene(new Scene(root, 400, 300));
stage.setTitle("Stage");
stage.show();
}
public static void main(final String... args) {
launch(args);
}
}
Y aquí están los resultados que obtengo:
Nota: no todos los caracteres en el ejemplo son de planos suplementarios, y uno de los caracteres solo se representa correctamente en la consola.