summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/gfx/_gfxBidiSupport.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo/dojox/gfx/_gfxBidiSupport.js')
-rw-r--r--js/dojo/dojox/gfx/_gfxBidiSupport.js405
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
+});
+