123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- 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
- });
|