Support for Farsi/Arabic texts in Three.js

馋奶兔 提交于 2021-02-08 09:01:06

问题


I need to show some text in Persian/Arabic language. I loaded a font including characters and I used TextGeometry to create a text on the scene:

var loader = new THREE.FontLoader();
loader.load('B Zar_Regular.js', function (font) {
    var textGeo = new THREE.TextGeometry('سلام!', {
        font: font,
        size: 1,
        height: 0.05,
        curveSegments: 12,
    });
    var material = new THREE.MeshNormalMaterial();
    var textMesh = new THREE.Mesh(textGeo, material);
    textMesh.position.x = 15;
    scene.add(textMesh);
});

I was expecting to see سلام! but the output was:

letters are separated and order of characters is reversed mistakenly. After all it seems threejs do not support rtl languages. Am I right or I missed something? Is there any workaround as a quick solution? Thanks.


回答1:


First of all I found very useful blog post here by Chris Loer. He has written a plugin (mapbox-gl-rtl-text.js) that solves the problem.

Usage example:

var rtlText = require('mapbox-gl-rtl-text');
var arabicString = "سلام";
var shapedArabicText = rtlText.applyArabicShaping(arabicString);
var readyForDisplay = rtlText.processBidirectionalText(shapedArabicText, []);


PS: When I used this plugin with common Farsi fonts some of letters was not shown so I add some extra code to fix it.
RtlTextHelper.farsify("سلام");

Usage example:

private createTextMesh(font, text) {
        var shapedText = RtlTextHelper.farsify(text);
        var fontSize = 0.3;
        var textHieght = 0.2;
        var material = new THREE.MeshBasicMaterial({
            color: this.colors.label.normal,
            side: THREE.DoubleSide
        });
        var textGeo = new THREE.TextGeometry(shapedText, {
            font: font,
            size: fontSize,
            height: 0.05,
            curveSegments: 12
        });
        var textMesh = new THREE.Mesh(textGeo, material);
        textGeo.computeBoundingBox();
        var box = new THREE.Box3().setFromObject(textMesh);
        var textLength = box.max.x;
        return {
            mesh: textMesh,
            hieght: textHieght,
            font: {
                size: fontSize
            },
            length: textLength
        };
    }



回答2:


This is a complex problem. Ligatures, the calligraphic strokes which connect letters, most familiar to western readers as a component of cursive English, is not optional in Arabic. Ligatures are intrinsic to the language, changing the meaning and formality of the text. The font.js class is designed to take each letter (glyph) one by one and convert it to a shape path. This doesn't work in Arabic because joining rules are complex depending on specific letter combinations.

I do not believe there is a fix that can be put in place in three.js. Although I would be anxious to know what the potential solution is as mentioned by O.P.

It may be possible to convert isolated letters to final Arabic ligatured forms via this script, or maybe this one among others. The final presentation forms might then be sent to Three.js for display so that the ligature joins are handled already and three.js receives the final ligatured forms rather than the isolated glyphs.

It may be a simpler task to convert text to svg paths using a text to path converter and then using the SVGLoader.js in three.js to load the letters as paths for extrusion. But this would have to be tested to ensure the conversion of text to a path handles Arabic at all and then if it does, the ligature joins will also need to be checked for accuracy.



来源:https://stackoverflow.com/questions/44920527/support-for-farsi-arabic-texts-in-three-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!