diff options
Diffstat (limited to 'js/dojo/dojox/gfx/_gfxBidiSupport.js')
| -rw-r--r-- | js/dojo/dojox/gfx/_gfxBidiSupport.js | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/js/dojo/dojox/gfx/_gfxBidiSupport.js b/js/dojo/dojox/gfx/_gfxBidiSupport.js new file mode 100644 index 0000000..071ef10 --- /dev/null +++ b/js/dojo/dojox/gfx/_gfxBidiSupport.js @@ -0,0 +1,405 @@ +//>>built +define("dojox/gfx/_gfxBidiSupport", ["./_base", "dojo/_base/lang","dojo/_base/sniff", "dojo/dom", "dojo/_base/html", "dojo/_base/array", + "./utils", "./shape", "dojox/string/BidiEngine"], + function(g, lang, has, dom, html, arr, utils, shapeLib, BidiEngine){ + lang.getObject("dojox.gfx._gfxBidiSupport", true); + /*===== g = dojox.gfx; =====*/ + switch (g.renderer){ + case 'vml': + g.isVml = true; + break; + case 'svg': + g.isSvg = true; + if(g.svg.useSvgWeb){ + g.isSvgWeb = true; + } + break; + case 'silverlight': + g.isSilverlight = true; + break; + case 'canvas': + g.isCanvas = true; + break; + } + + var bidi_const = { + LRM : '\u200E', + LRE : '\u202A', + PDF : '\u202C', + RLM : '\u200f', + RLE : '\u202B' + }; + + // the object that performs text transformations. + var bidiEngine = new BidiEngine(); + + lang.extend(g.shape.Surface, { + // textDir: String + // Will be used as default for Text/TextPath/Group objects that created by this surface + // and textDir wasn't directly specified for them, though the bidi support was loaded. + // Can be setted in two ways: + // 1. When the surface is created and textDir value passed to it as fourth + // parameter. + // 2. Using the setTextDir(String) function, when this function is used the value + // of textDir propogates to all of it's children and the children of children (for Groups) etc. + textDir: "", + + setTextDir: function(/*String*/newTextDir){ + // summary: + // Used for propogation and change of textDir. + // newTextDir will be forced as textDir for all of it's children (Group/Text/TextPath). + setTextDir(this, newTextDir); + }, + + getTextDir: function(){ + return this.textDir; + } + }); + + lang.extend(g.Group, { + // textDir: String + // Will be used for inheritance, or as default for text objects + // that textDir wasn't directly specified for them but the bidi support was required. + textDir: "", + + setTextDir: function(/*String*/newTextDir){ + // summary: + // Used for propogation and change of textDir. + // newTextDir will be forced as textDir for all of it's children (Group/Text/TextPath). + setTextDir(this, newTextDir); + }, + + getTextDir: function(){ + return this.textDir; + } + }); + + lang.extend(g.Text, { + // summary: + // Overrides some of dojox.gfx.Text properties, and adds some + // for bidi support. + + // textDir: String + // Used for displaying bidi scripts in right layout. + // Defines the base direction of text that displayed, can have 3 values: + // 1. "ltr" - base direction is left to right. + // 2. "rtl" - base direction is right to left. + // 3. "auto" - base direction is contextual (defined by first strong character). + textDir: "", + + formatText: function (/*String*/ text, /*String*/ textDir){ + // summary: + // Applies the right transform on text, according to renderer. + // text: + // the string for manipulation, by default return value. + // textDir: + // Text direction. + // Can be: + // 1. "ltr" - for left to right layout. + // 2. "rtl" - for right to left layout + // 3. "auto" - for contextual layout: the first strong letter decides the direction. + // discription: + // Finds the right transformation that should be applied on the text, according to renderer. + // Was tested in: + // Renderers (browser for testing): + // canvas (FF, Chrome, Safari), + // vml (IE), + // svg (FF, Chrome, Safari, Opera), + // silverlight (IE, Chrome, Safari, Opera), + // svgWeb(FF, Chrome, Safari, Opera, IE). + // Browsers [browser version that was tested]: + // IE [6,7,8], FF [3.6], + // Chrome (latest for March 2011), + // Safari [5.0.3], + // Opera [11.01]. + + if(textDir && text && text.length > 1){ + var sourceDir = "ltr", targetDir = textDir; + + if(targetDir == "auto"){ + //is auto by default + if(g.isVml){ + return text; + } + targetDir = bidiEngine.checkContextual(text); + } + + if(g.isVml){ + sourceDir = bidiEngine.checkContextual(text); + if(targetDir != sourceDir){ + if(targetDir == "rtl"){ + return !bidiEngine.hasBidiChar(text) ? bidiEngine.bidiTransform(text,"IRNNN","ILNNN") : bidi_const.RLM + bidi_const.RLM + text; + }else{ + return bidi_const.LRM + text; + } + } + return text; + } + + if(g.isSvgWeb){ + if(targetDir == "rtl"){ + return bidiEngine.bidiTransform(text,"IRNNN","ILNNN"); + } + return text; + } + + if(g.isSilverlight){ + return (targetDir == "rtl") ? bidiEngine.bidiTransform(text,"IRNNN","VLYNN") : bidiEngine.bidiTransform(text,"ILNNN","VLYNN"); + } + + if(g.isCanvas){ + return (targetDir == "rtl") ? bidi_const.RLE + text + bidi_const.PDF : bidi_const.LRE + text + bidi_const.PDF; + } + + if(g.isSvg){ + if(has("ff")){ + return (targetDir == "rtl") ? bidiEngine.bidiTransform(text,"IRYNN","VLNNN") : bidiEngine.bidiTransform(text,"ILYNN","VLNNN"); + } + if(has("chrome") || has("safari") || has("opera")){ + return bidi_const.LRM + (targetDir == "rtl" ? bidi_const.RLE : bidi_const.LRE) + text + bidi_const.PDF; + } + } +} + return text; + }, + + bidiPreprocess: function(newShape){ + return newShape; + } + }); + + lang.extend(g.TextPath, { + // textDir: String + // Used for displaying bidi scripts in right layout. + // Defines the base direction of text that displayed, can have 3 values: + // 1. "ltr" - base direction is left to right. + // 2. "rtl" - base direction is right to left. + // 3. "auto" - base direction is contextual (defined by first strong character). + textDir: "", + + formatText: function (/*String*/text, /*String*/textDir){ + // summary: + // Applies the right transform on text, according to renderer. + // text: the string for manipulation, by default return value. + // textDir: text direction direction. + // Can be: + // 1. "ltr" - for left to right layout. + // 2. "rtl" - for right to left layout + // 3. "auto" - for contextual layout: the first strong letter decides the direction. + // discription: + // Finds the right transformation that should be applied on the text, according to renderer. + // Was tested in: + // Renderers: + // canvas (FF, Chrome, Safari), vml (IE), svg (FF, Chrome, Safari, Opera), silverlight (IE8), svgWeb(FF, Chrome, Safari, Opera, IE). + // Browsers: + // IE [6,7,8], FF [3.6], Chrome (latest for February 2011), Safari [5.0.3], Opera [11.01]. + + if(textDir && text && text.length > 1){ + var sourceDir = "ltr", targetDir = textDir; + + if(targetDir == "auto"){ + //is auto by default + if(g.isVml){ + return text; + } + targetDir = bidiEngine.checkContextual(text); + } + + if(g.isVml){ + sourceDir = bidiEngine.checkContextual(text); + if(targetDir != sourceDir){ + if(targetDir == "rtl"){ + return !bidiEngine.hasBidiChar(text) ? bidiEngine.bidiTransform(text,"IRNNN","ILNNN") : bidi_const.RLM + bidi_const.RLM + text; + }else{ + return bidi_const.LRM + text; + } + } + return text; + } + if(g.isSvgWeb){ + if(targetDir == "rtl"){ + return bidiEngine.bidiTransform(text,"IRNNN","ILNNN"); + } + return text; + } + //unlike the g.Text that is rendered in logical layout for Bidi scripts. + //for g.TextPath in svg always visual -> bidi script is unreadable (except Opera). + if(g.isSvg){ + if(has("opera")){ + text = bidi_const.LRM + (targetDir == "rtl"? bidi_const.RLE : bidi_const.LRE) + text + bidi_const.PDF; + }else{ + text = (targetDir == "rtl") ? bidiEngine.bidiTransform(text,"IRYNN","VLNNN") : bidiEngine.bidiTransform(text,"ILYNN","VLNNN"); + } + } + } + return text; + }, + bidiPreprocess: function(newText){ + if(newText && (typeof newText == "string")){ + this.origText = newText; + newText = this.formatText(newText,this.textDir); + } + return newText; + } + }); + + var extendMethod = function(shape, method, before, after){ + // Some helper function. Used for extending metod of shape. + // shape: Object + // The shape we overriding it's metod. + // method: String + // The method that is extended, the original metod is called before or after + // functions that passed to extendMethod. + // before: function + // If defined this function will be executed before the original method. + // after: function + // If defined this function will be executed after the original method. + var old = shape.prototype[method]; + shape.prototype[method] = + function(){ + var rBefore; + if (before){ + rBefore = before.apply(this, arguments); + } + var r = old.call(this, rBefore); + if (after){ + r = after.call(this, r, arguments); + } + return r; + }; + }; + + var bidiPreprocess = function(newText){ + if (newText){ + if (newText.textDir){ + newText.textDir = validateTextDir(newText.textDir); + } + if (newText.text && (newText.text instanceof Array)){ + newText.text = newText.text.join(","); + } + } + if(newText && (newText.text != undefined || newText.textDir) && (this.textDir != newText.textDir || newText.text != this.origText)){ + // store the original text. + this.origText = (newText.text != undefined) ? newText.text : this.origText; + if(newText.textDir){ + this.textDir = newText.textDir; + } + newText.text = this.formatText(this.origText,this.textDir); + } + return this.bidiPreprocess(newText); + + }; + + // Istead of adding bidiPreprocess to all renders one by one + // use the extendMethod, at first there's a need for bidi transformation + // on text then call to original setShape. + extendMethod(g.Text,"setShape", bidiPreprocess, null); + extendMethod(g.TextPath,"setText", bidiPreprocess, null); + + var restoreText = function(origObj){ + var obj = lang.clone(origObj); + if (obj && this.origText){ + obj.text = this.origText; + } + return obj; + }; + + // Istead of adding restoreText to all renders one by one + // use the extendMethod, at first get the shape by calling the original getShape, + // than resrore original text (without the text transformations). + extendMethod(g.Text, "getShape", null, restoreText); + extendMethod(g.TextPath, "getText", null, restoreText); + + var groupTextDir = function(group, args){ + var textDir; + if (args && args[0]){ + textDir = validateTextDir(args[0]); + } + group.setTextDir(textDir ? textDir : this.textDir); + return group; // dojox.gfx.Group + }; + + // In creation of Group there's a need to update it's textDir, + // so instead of doing it in renders one by one (vml vs others) + // use the extendMethod, at first the original createGroup is applied, the + // groupTextDir which is setts Group's textDir as it's father's or if was defined + // by user by this value. + extendMethod(g.Surface, "createGroup", null, groupTextDir); + extendMethod(g.Group, "createGroup", null, groupTextDir); + + var textDirPreprocess = function(text){ + // inherit from surface / group if textDir is defined there + if(text){ + var textDir = text.textDir ? validateTextDir(text.textDir) : this.textDir; + if(textDir){ + text.textDir = textDir; + } + } + return text; + }; + + // In creation there's a need to some preprocess, + // so instead of doing it in renders one by one (vml vs others) + // use the extendMethod, at first the textDirPreprocess function handles the input + // then the original createXXXXXX is applied. + extendMethod(g.Surface,"createText", textDirPreprocess, null); + extendMethod(g.Surface,"createTextPath", textDirPreprocess, null); + extendMethod(g.Group,"createText", textDirPreprocess, null); + extendMethod(g.Group,"createTextPath", textDirPreprocess, null); + + g.createSurface = function(parentNode, width, height, textDir) { + var s = g[g.renderer].createSurface(parentNode, width, height); + var tDir = validateTextDir(textDir); + + if(g.isSvgWeb){ + s.textDir = tDir ? tDir : html.style(dom.byId(parentNode),"direction"); + return s; + } + // if textDir was defined use it, else get default value. + //s.textDir = tDir ? tDir : html.style(s.rawNode,"direction"); + if(g.isVml || g.isSvg || g.isCanvas){ + s.textDir = tDir ? tDir : html.style(s.rawNode,"direction"); + } + if(g.isSilverlight){ + // allow this once rawNode will be able for the silverlight + //s.textDir = tDir ? tDir : dojo.style(s.rawNode,"direction"); + s.textDir = tDir ? tDir : html.style(s._nodes[1],"direction"); + } + + return s; + }; + + // some helper functions + + function setTextDir(/*Object*/ obj, /*String*/ newTextDir){ + var tDir = validateTextDir(newTextDir); + if (tDir){ + g.utils.forEach(obj,function(e){ + if(e instanceof g.Surface || e instanceof g.Group){ + e.textDir = tDir; + } + if(e instanceof g.Text){ + e.setShape({textDir: tDir}); + } + if(e instanceof g.TextPath){ + e.setText({textDir: tDir}) + } + }, obj); + } + return obj; + } + + function validateTextDir(textDir){ + var validValues = ["ltr","rtl","auto"]; + if (textDir){ + textDir = textDir.toLowerCase(); + if (arr.indexOf(validValues, textDir) < 0){ + return null; + } + } + return textDir; + } + + return g; // return gfx api augmented with bidi support +}); + |
