{"id":6243,"date":"2012-10-26T07:00:00","date_gmt":"2012-10-26T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/10\/26\/whether-the-unicode-bidi-algorithm-is-intuitive-depends-on-your-definition-of-intuitive\/"},"modified":"2012-10-26T07:00:00","modified_gmt":"2012-10-26T07:00:00","slug":"whether-the-unicode-bidi-algorithm-is-intuitive-depends-on-your-definition-of-intuitive","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20121026-00\/?p=6243","title":{"rendered":"Whether the Unicode Bidi algorithm is intuitive depends on your definition of &#034;intuitive&#034;"},"content":{"rendered":"<p>In Windows, we spend a good amount of time with the <a href=\"http:\/\/blogs.msdn.com\/b\/shawnste\/archive\/2006\/06\/27\/647915.aspx\"> pseudo-mirrored build<\/a>. And one of the things that you notice is that pseudo-mirrored text comes out looking really weird. For example, the string <span style=\"border: black .75pt solid;padding-left: .2ex;padding-right: .2ex\"> really? (yup).<\/span> comes out pseudo-mirrored as <span style=\"border: black .75pt solid;padding-left: .2ex;padding-right: .2ex\"> .(really? (yup<\/span>. Just for fun, here&#8217;s here&#8217;s how your browser renders it:<\/p>\n<blockquote class=\"m\"><p> really? (yup). <\/p><\/blockquote>\n<p> Even stranger, the IPv6 address <span style=\"border: black .75pt solid;padding-left: .2ex;padding-right: .2ex\"> 2001:db8:85a3::8a2e:370:7334<\/span> comes out as <span style=\"border: black .75pt solid;padding-left: .2ex;padding-right: .2ex\"> db8:85a3::8a2e:370:7334:2001<\/span>. (The IPv6 address was the string that prompted this article.) The result of the RTL IPv6 address is even weirder if you force a line break at a particular point. If your browser follows the Unicode Bidi algorithm, you can resize the box below to see how the line break position affects the rendering.<\/p>\n<blockquote class=\"m\"><p> 2001:db8:85a3::8a2e:370:7334 <\/p><\/blockquote>\n<p> If your browser doesn&#8217;t follow the Unicode Bidi algorithm, or if you can&#8217;t resize the window, here&#8217;s what you get:<\/p>\n<table style=\"border-collapse: collapse\">\n<tr>\n<td valign=\"baseline\" style=\"padding-right: 1em\">No line break<\/td>\n<td style=\"font-family: monospace;border: solid black .75pt;text-align: right\" nowrap>db8:85a3::8a2e:370:7334:2001<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\">Line break<\/td>\n<td align=\"right\" style=\"font-family: monospace;border: solid black .75pt\">:2001<br \/>db8:85a3::8a2e:370:7334<\/td>\n<\/tr>\n<\/table>\n<p> &#8220;Is this a bug?&#8221;\n No.\n Well, maybe yes.\n It depends.\n But mostly yes.\n Windows is following the <a href=\"http:\/\/www.unicode.org\/reports\/tr9\/\"> Unicode Bidirectional Algorithm<\/a>. So the part that&#8217;s not a bug is &#8220;Windows is correctly following an international standard.&#8221; The weirdness you&#8217;re seeing is just a consequence of following the standard.\n Let&#8217;s look at what&#8217;s going on.\n When you render text in RTL context, what you&#8217;re saying is &#8220;Render this text in the form you would see it if it appeared in a newspaper printed in an RTL language.&#8221; For illustration, we follow the convention that uppercase characters are considered to be in an RTL script, lowercase characters are considered to be in an LTR script, and non-letters stand for themselves.\n Say you want to render the string &#8220;NEXT COMES john smith.&#8221; A newspaper would say, &#8220;Well, my readership expects things to be laid out right to left. The string &#8216;john smith&#8217; is a foreign name inserted into a paragraph that otherwise is written my readers&#8217; native language. If the name were in my readers&#8217; native language, I would render it as<\/p>\n<blockquote class=\"m\" style=\"text-align: right\"><p> .HTIMS NHOJ SEMOC TXEN <\/p><\/blockquote>\n<p> Since the name is in a foreign language, I will treat it as an opaque &#8216;name blob&#8217; that got inserted into my otherwise beautiful RTL sentence.&#8221;<\/p>\n<blockquote class=\"m\" style=\"text-align: right\"><p> .<span style=\"border: solid .75pt black\">john smith<\/span> SEMOC TXEN <\/p><\/blockquote>\n<p> (The black outline is not part of the actual output. I am using it to highlight that the phrase <i>john smith<\/i> is being treated as a single unit.)\n This also explains why &#8220;hello.&#8221; comes out as &#8220;<span dir=\"rtl\">hello.<\/span>&#8220;. The LTR text is treated as a blob inside an otherwise RTL sentence.<\/p>\n<blockquote class=\"m\" style=\"text-align: right\"><p> .<span style=\"border: solid .75pt black\">hello<\/span> <\/p><\/blockquote>\n<p> Things get weirder once parentheses and digits and more complex punctuation marks are thrown into the mix. For example, the Unicode Bidirectional Algorithm has to figure out that in the text &#8220;IT IS A bmw 500, OK.&#8221; the &#8220;500&#8221; is attached to the LTR text &#8220;bmw&#8221;, resulting in<\/p>\n<blockquote class=\"m\" style=\"text-align: right\"><p> .KO ,<span style=\"border: solid .75pt black\">bmw 500<\/span> A SI TI <\/p><\/blockquote>\n<p> And it also needs to work out the correct text rendering order when you have RTL text embedded inside LTR text, all of which is embedded inside other RTL text, as illustrated by the brain-teaser &#8220;DID YOU SAY &rsquo;he said &ldquo;car MEANS CAR&rdquo;&lsquo;?&#8221;\n But maybe the standard is buggy. The problem is that the Unicode Bidirectional Algorithm is designed for text, so when you ask it to render things that aren&#8217;t text (such as IPv6 addresses and URLs), the results can be nonsensical.\n At least for the IPv6 case, you can work around the problem by explicitly marking the IPv6 address as LTR, so that the Unicode Bidirectional Algorithm doesn&#8217;t get involved, and the characters are rendered left-to-right in the order they were written.\n <b>Exercise<\/b>: Study the Unicode Bidirectional Algorithm and explain why <span style=\"border: black .75pt solid;padding-left: .2ex;padding-right: .2ex\"> really? (yup).<\/span> comes out as <span style=\"border: black .75pt solid;padding-left: .2ex;padding-right: .2ex\"> .(really? (yup<\/span>.<\/p>\n<p> <b>Bonus reading<\/b>: <a href=\"http:\/\/www.w3.org\/International\/articles\/inline-bidi-markup\/\"> What you need to know about the bidi algorithm and inline markup<\/a>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Windows, we spend a good amount of time with the pseudo-mirrored build. And one of the things that you notice is that pseudo-mirrored text comes out looking really weird. For example, the string really? (yup). comes out pseudo-mirrored as .(really? (yup. Just for fun, here&#8217;s here&#8217;s how your browser renders it: really? (yup). Even [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-6243","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>In Windows, we spend a good amount of time with the pseudo-mirrored build. And one of the things that you notice is that pseudo-mirrored text comes out looking really weird. For example, the string really? (yup). comes out pseudo-mirrored as .(really? (yup. Just for fun, here&#8217;s here&#8217;s how your browser renders it: really? (yup). Even [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/6243","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=6243"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/6243\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=6243"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=6243"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=6243"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}