I am trying to use the fillText() method on an HTML5 Canvas\' 2d Context to draw a string written in Arabic. It works perfectly, until I put a punctuation mark at the end of
Setting the dir option is for the whole canvas - for individual strings that behave badly, you might consider manually adding an RTL marker (U+200F) after the quote.
You don't need to set the direction for each individual string. See the following example which also shows the proper use of implicit bidi control marks for proper display order:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<canvas id="myCanvas" width="700" dir="rtl" height="250" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script type="text/javascript" charset="utf-8">
var c = document.getElementById("myCanvas");
var cArabic = c.getContext("2d");
cArabic.font="25px Arial";
// Simple Sentence with punctuation.
var str1 = "این یک آزمایش است.";
// Few sentences with punctuation and numerals.
var str2 = "۱ آزمایش. 2 آزمایش، سه آزمایش & Foo آزمایش!";
// Needs implicit bidi marks to display correctly.
var str3 = "آزمایش برای Foo Ltd. و Bar Inc. باشد که آزموده شود.";
// Implicit bidi marks added; "Foo Ltd.‎ و Bar Inc.‎"
var str4 = "آزمایش برای Foo Ltd. و Bar Inc. باشد که آزموده شود.";
cArabic.fillText(str1, 600, 60);
cArabic.fillText(str2, 600, 100);
cArabic.fillText(str3, 600, 140);
cArabic.fillText(str4, 600, 180);
</script>
</body>
</html>
And here is the output:
You can do it with that:
ctx.textAlign="end";
or
ctx.textAlign="right"
And to make it again left-to-right:
ctx.textAlign="start";
The problem is that the '.' character is 'directional neutral character', it means that it get the direction from the next strong directional character, if there is no character afterwards, it get it from the container. In your case it is the latter one. One solution, as already found, is to make the container right-to-left. But there are still two other solutions :
1- Put another invisible strong right-to-left directional character after the '.'. Fortunately the unicode has one special character for that which is "right-to-left mark" (U+200F)
2- Put the "right-to-left override character" (U+202E) before the text, so after this mark any neutral character get the right-to-left direction. You can end the override by adding "pop directional formatting" character (U+202C).
I changed the @shervin's sample code to demonstrate it.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<canvas id="myCanvas" width="700" height="250" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script type="text/javascript" charset="utf-8">
var c = document.getElementById("myCanvas");
var cArabic = c.getContext("2d");
cArabic.font="20px Arial";
//option 1 : adding right-to-left mark at the end to put the '.' between two strong right to left charachters, so it will treated as right to left.
var str1 = "این یک آزمایش است." + "\u200F";
//option 2 : adding right-to-left override at the begining of the text so every neutral charachter afterward becomes righ to left.
var str2;
str2 = "\u202E";
str2+= "این یک آزمایش است.";
// you might want to finish the override by 'pop directional formatting' charachter
str2 += "\u202C";
cArabic.fillText(str1, 200, 30);
cArabic.fillText(str2, 200, 70);
</script>
</body>
</html>
Result image
There are other solutions. You can find them in unicode specification in this page. They are, "direction isolation" (U+2067) which has rendering problem in Chrome. And "direction embedding" with U+202B, which is similar to direction override.