////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Silverlight Font Binding Helper  1.6
//                                                    write by code6421
//
//                                                             2007.10.05               
//
//Use Font File :
//   <TextBlock  FontFamily="HanWangMingMedium" Width="400" Canvas.Top="180"  FontSize="36" Text="這是測試字形換行" Tag="DBCS:wt002.zip"/>
//Use XPS File :
//   <TextBlock Name="MyTextBlock" Width="67" Height="23.2" Canvas.Left="29" Canvas.Top="10" Foreground="#FFEFEFEF" Text="我是中文,而且只是部份字型哦!!!" FontFamily="HanWangMingMedium" FontSize="24" Tag="XPS:GetFontsXPS.aspx?FontName=HanWangMingMedium"  />
//Dynamic Set Font/XPS :
//
//  var fh = new SilverlightHelper.FontHelper(this.rootElement);
//  // set xps  setTextWithXPS  : function(ctrl,text,xpsName,fontFamily)
//  fh.setTextWithXPS(sender.findName("DynamicText"),"我是動態由JavaScript設定的","GetFontsXPS.aspx?FontName=HanWangMingMedium","HanWangMingMedium");		
//  //set font  setTextWithFont : function(ctrl,text,fontFileName,fontFamily)
//  fh.setTextWithFont(sender.findName("DynamicText"),"我是動態由JavaScript設定的","wt001.zip");	
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var keyStr = "ABCDEFGHIJKLMNOP" +
             "QRSTUVWXYZabcdef" +
             "ghijklmnopqrstuv" +
             "wxyz0123456789+/" +
             "=";
             
function encode64(input) 
{
    input = escape(input);
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;
    do 
    {
       chr1 = input.charCodeAt(i++);
       chr2 = input.charCodeAt(i++);
       chr3 = input.charCodeAt(i++);
       enc1 = chr1 >> 2;
       enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
       enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
       enc4 = chr3 & 63;
       if (isNaN(chr2)) 
       {
           enc3 = enc4 = 64;
       } 
       else if (isNaN(chr3)) {
           enc4 = 64;
       }
       output = output + 
       keyStr.charAt(enc1) + 
       keyStr.charAt(enc2) + 
       keyStr.charAt(enc3) + 
       keyStr.charAt(enc4);
       chr1 = chr2 = chr3 = "";
       enc1 = enc2 = enc3 = enc4 = "";
    } while (i < input.length);
      return output;
}


if (!window.SilverlightHelper)
	window.SilverlightHelper = {};

SilverlightHelper.createDelegate = function(instance, method) {
	return function() {
        return method.apply(instance, arguments);
    }
}

SilverlightHelper.FontBinding = function(ctrl,bindingExpression)
{
   if(!bindingExpression || bindingExpression == '')
      return;   
   this.bindingComplete = false;
   this.ctrl = ctrl;
   var temp = bindingExpression.split(':');
   if(temp.length != 2) 
   {
      this.bindingComplete = false;
      return;
   }
   if(temp[0] == 'DBCS')
   {
      var parseDefault = temp[1].split(';');
      if(parseDefault.length == 2 && parseDefault[1] == "default")
      {
         this.defaultFont = true;
         this.fontFileName = parseDefault[0];
      }   
      else
      {
         this.defaultFont = false;   
         this.fontFileName = temp[1];         
      }   
   }
   else if(temp[0] == "XPS")
   {
      var parseDefault = temp[1].split(';');
      if(parseDefault.length == 2 && parseDefault[1] == "default")
      {
         this.defaultFont = true;
         this.fontFileName = parseDefault[0];
      }   
      else
      {
         this.defaultFont = false;   
         this.fontFileName = temp[1];         
      }   
      this.xpsService = true;
   }   
   this.bindingComplete = true;
}

SilverlightHelper.FontBinding.prototype = 
{
   updateFont : function(dataItem)
   {
      if(this.fontFileName)
      {
         try
         {
            this.ctrl.setFontSource(dataItem);            
         }
         catch(err)
         {
            alert(err.message);
         }
      }   
   }
}

//global fonts cache
var _cached_downloadedFont = new Array();

SilverlightHelper.FontHelper = function(rootElement) 
{
   this.rootElement = rootElement;
   this.host = this.rootElement.getHost();
   this.bindingControls = new Array();   
}

SilverlightHelper.FontHelper.prototype =
{  
   initialize : function()
   {
      this._childWorker(this.rootElement,false); 
      //find default font. 
      for(var i = 0; i < this.bindingControls.length; i++)
      {
         if(this.bindingControls[i].defaultFont)
         {
            this.defaultFont = this.bindingControls[i];
            break;
         }
      }
      //collect texts with XPS at this page.
      this._collectPageXPSText();
      if(this.xpsServiceUrl)
      {
	     //this._acquireFontWithXPS(this.xpsServiceUrl+"&Data="+encode64(this.pageXPSText),this.pageXPSText,
	       //                     SilverlightHelper.createDelegate(this, this._xpsHandleCompleted));
	       this._acquireFontWithXPS(this.xpsServiceUrl,this.pageXPSText,
	                            SilverlightHelper.createDelegate(this, this._xpsHandleCompleted));
	   	 this._addCachedFont(this.xpsServiceUrl);  
      }
      else if(this.defaultFont)
      {
	   	 this._addCachedFont(this.defaultFont.fontFileName);
	   	 this._acquireFont(this.defaultFont.fontFileName,
	                  SilverlightHelper.createDelegate(this, this._defaultFontHandleCompleted));
      }   
      else
         this._initDownload();
   },
   _acquireFont : function(url,completedProc)
   {
      var downloader = this.host.createObject("downloader");
      this._createProgressBar(this.rootElement);	  
       	   
      // Add Completed event.
      downloader.addEventListener("Completed", completedProc);
      downloader.addEventListener("DownloadProgressChanged", SilverlightHelper.createDelegate(this, this._onDownloadProgressChanged));       
       
      // Initialize the Downloader request.               
      downloader.open("GET", url);
      downloader.send();
   },
   _acquireFontWithXPS : function(url,text,completedProc)
   {
      if(text.length > 100)
      {
         this.splitDownloader = new Array();
         this.splitDownloader.length = (text.length / 100);
         if((text.length % 100) > 0)
            this.splitDownloader.length++;
         for(var i = 0; i < this.splitDownloader.length; i++)
         {
             this.splitDownloader[i] = text.substring(0,100);
             text = text.substring(100,text.length);
         }
         this.splitDownloaderIndex = 0;
         this.spliturl = url;
      }
      
      var downloader = this.host.createObject("downloader");
      this._createProgressBar(this.rootElement);	  
       	   
      // Add Completed event.
      downloader.addEventListener("Completed", completedProc);
      downloader.addEventListener("DownloadProgressChanged", SilverlightHelper.createDelegate(this, this._onDownloadProgressChanged));       
       
      // Initialize the Downloader request.         
      if(this.splitDownloader != null)
          downloader.open("GET",url+"&SPLIT=true&Data="+encode64(this.splitDownloader[0]));
      else
          downloader.open("GET", url+"&Data="+encode64(text));
      downloader.send();
   },
   _collectPageXPSText : function()
   {
      this.pageXPSText = '';
      for(var i = 0; i < this.bindingControls.length; i++)
      {
         if(this.bindingControls[i].xpsService)
         {            
            if(!this.xpsServiceUrl)
               this.xpsServiceUrl = this.bindingControls[i].fontFileName; // we only support one xps service at page(static mode).       
            if(this.bindingControls[i].fontFileName == this.xpsServiceUrl)
               this.pageXPSText = this.pageXPSText + this.bindingControls[i].ctrl.text;
         }   
      }
   },
   _initDownload : function()
   {
       if(this.bindingControls.length > 0)
       {
          this.currentIndex = 0;
          this._startDownload();
       }    
   },
   _addCachedFont : function(fontFileName)
   {
      _cached_downloadedFont.length++;
      _cached_downloadedFont[_cached_downloadedFont.length-1] = {}; 
      _cached_downloadedFont[_cached_downloadedFont.length-1].fontFileName = fontFileName;
   },
   _findCachedFont : function(fontFileName)
   {
      for(var i = 0; i < _cached_downloadedFont.length; i++)
      {
         if(_cached_downloadedFont[i].fontFileName == fontFileName)
            return _cached_downloadedFont[i];
      }
   },
   _continueDownload : function()
   {
      if(this.currentIndex < this.bindingControls.length)
      {
          this.currentIndex++;
          this._startDownload();
      }   
   },
   _startDownload : function()
   {
       if(!this.bindingControls[this.currentIndex]) return;       
       if(this.bindingControls[this.currentIndex].defaultFont)
       {
          this._continueDownload();
          return;
       }
       if(this.bindingControls[this.currentIndex].fontFileName == "default")
       {
          this.bindingControls[this.currentIndex].updateFont(this.defaultFontData);
          this._continueDownload();
          return;
       }
       var cachedFont = this._findCachedFont(this.bindingControls[this.currentIndex].fontFileName);       
       if(cachedFont)
       {
          this.bindingControls[this.currentIndex].updateFont(cachedFont.fontData);
          this._continueDownload();
          return;
       }
          
       this._addCachedFont(this.bindingControls[this.currentIndex].fontFileName);   
       
       if(this.bindingControls[this.currentIndex].xpsService)
          this._acquireFontWithXPS(this.bindingControls[this.currentIndex].fontFileName,this.bindingControls[this.currentIndex].ctrl.text,
	                               SilverlightHelper.createDelegate(this, this._xpsHandleCompletedNormal));
       else
          this._acquireFont(this.bindingControls[this.currentIndex].fontFileName,
	                  SilverlightHelper.createDelegate(this, this._handleCompleted));
   },
   setTextWithFont : function(ctrl,text,fontFileName,fontFamily)
   {     
       ctrl.text = text
       var font = this._findCachedFont(fontFileName);
       if(font)
          ctrl.setFontSource(font.fontData);
       else
       {   
          this._addCachedFont(fontFileName);
          this.pendingCtrl = ctrl;
       
          this._acquireFont(fontFileName,
	                  SilverlightHelper.createDelegate(this, this._dynamicFontHandleCompleted));	
       }  
       if(fontFamily)
          ctrl.fontFamily = fontFamily;
   },
   setTextWithXPS  : function(ctrl,text,xpsName,fontFamily)
   {
       ctrl.text = text;       
       this.pendingCtrl = ctrl;       
       
       this._acquireFontWithXPS(xpsName,ctrl.text,
	                  SilverlightHelper.createDelegate(this, this._dynamicXPSHandleCompleted));
	   if(fontFamily)
          ctrl.fontFamily = fontFamily;
   },   
   _handleCompleted : function(sender, eventArgs)
   {
      _cached_downloadedFont[_cached_downloadedFont.length-1].fontData = sender;
      this.bindingControls[this.currentIndex].updateFont(sender);
      this._cleanProgressBar();
      this._continueDownload();
   },
   _defaultFontHandleCompleted : function(sender, eventArgs)
   {
      _cached_downloadedFont[_cached_downloadedFont.length-1].fontData = sender;
      this.defaultFontData = sender;
      this.defaultFont.updateFont(sender);      
      this._cleanProgressBar();
      this._initDownload();
   },  
   _xpsHandleCompletedNormal : function(sender, eventArgs)
   {      
      var splitSession = sender.ResponseText.split(':');
      if(splitSession[0] == "SPLIT_SESSION")
      {
         this._cleanProgressBar();
         this.splitDownloaderIndex++;
         var downloader = this.host.createObject("downloader");
         this._createProgressBar(this.rootElement);	         
         downloader.addEventListener("Completed", SilverlightHelper.createDelegate(this,this._xpsHandleCompletedNormal));
         downloader.addEventListener("DownloadProgressChanged", SilverlightHelper.createDelegate(this, this._onDownloadProgressChanged));     
         
         if(this.splitDownloaderIndex == this.splitDownloader.length-1)
         {
            downloader.open("GET",this.spliturl+"&SPLIT=true&SPLIT_END=true&SPLIT_SESSION="+splitSession[1]+"&Data="+encode64(this.splitDownloader[this.splitDownloaderIndex]));
            this.splitDownloaderIndex = null;
            this.splitDownloader = null;
         }  
         else
            downloader.open("GET",this.spliturl+"&SPLIT=true&SPLIT_SESSION="+splitSession[1]+"&Data="+encode64(this.splitDownloader[this.splitDownloaderIndex]));
         downloader.send();
         return;
      }      
      if(!this.pendingFile)
      {
        this.pendingFile = true;
        this._cleanProgressBar();
        
        this._acquireFont(sender.ResponseText,
	                  SilverlightHelper.createDelegate(this, this._xpsHandleCompletedNormal));	
        return;
      } 
      this.pendingFile = null;
      _cached_downloadedFont[_cached_downloadedFont.length-1].fontData = sender;
      this.bindingControls[this.currentIndex].updateFont(sender);
      this._cleanProgressBar();
      this._continueDownload();
   },
   _xpsHandleCompleted : function(sender, eventArgs)
   {
       var splitSession = sender.ResponseText.split(':');
      if(splitSession[0] == "SPLIT_SESSION")
      {
         this._cleanProgressBar();
         this.splitDownloaderIndex++;
         var downloader = this.host.createObject("downloader");
         this._createProgressBar(this.rootElement);	         
         downloader.addEventListener("Completed", SilverlightHelper.createDelegate(this,this._xpsHandleCompleted));
         downloader.addEventListener("DownloadProgressChanged", SilverlightHelper.createDelegate(this, this._onDownloadProgressChanged));     
         
         if(this.splitDownloaderIndex == this.splitDownloader.length-1)
         {
            downloader.open("GET",this.spliturl+"&SPLIT=true&SPLIT_END=true&SPLIT_SESSION="+splitSession[1]+"&Data="+encode64(this.splitDownloader[this.splitDownloaderIndex]));
            this.splitDownloaderIndex = null;
            this.splitDownloader = null;
         }  
         else
            downloader.open("GET",this.spliturl+"&SPLIT=true&SPLIT_SESSION="+splitSession[1]+"&Data="+encode64(this.splitDownloader[this.splitDownloaderIndex]));
         downloader.send();
         return;
      }      
         
      if(!this.pendingFile)
      {
        this.pendingFile = true;
        this._cleanProgressBar();
        
        this._acquireFont(sender.ResponseText,
	                  SilverlightHelper.createDelegate(this, this._xpsHandleCompleted));	
        return;
      } 
      this.pendingFile = null;      
      _cached_downloadedFont[_cached_downloadedFont.length-1].fontData = sender;
      this._cleanProgressBar();
      if(this.defaultFont)
      {
         this._addCachedFont(this.defaultFont.fontFileName);
         this._acquireFont(this.defaultFont.fontFileName,
	                  SilverlightHelper.createDelegate(this, this._defaultFontHandleCompleted));
      }
      else
         this._initDownload();
   },
   _dynamicFontHandleCompleted : function(sender, eventArgs)
   {  
      _cached_downloadedFont[_cached_downloadedFont.length-1].fontData = sender;
      this.pendingCtrl.setFontSource(sender);
      this.pendingCtrl = null;
      this._cleanProgressBar();
   },
   _dynamicXPSHandleCompleted : function(sender, eventArgs)
   {
      var splitSession = sender.ResponseText.split(':');
      if(splitSession[0] == "SPLIT_SESSION")
      {
         this._cleanProgressBar();
         this.splitDownloaderIndex++;
         var downloader = this.host.createObject("downloader");
         this._createProgressBar(this.rootElement);	         
         downloader.addEventListener("Completed", SilverlightHelper.createDelegate(this,this._dynamicXPSHandleCompleted));
         downloader.addEventListener("DownloadProgressChanged", SilverlightHelper.createDelegate(this, this._onDownloadProgressChanged));     
         
         if(this.splitDownloaderIndex == this.splitDownloader.length-1)
         {
            downloader.open("GET",this.spliturl+"&SPLIT=true&SPLIT_END=true&SPLIT_SESSION="+splitSession[1]+"&Data="+encode64(this.splitDownloader[this.splitDownloaderIndex]));
            this.splitDownloaderIndex = null;
            this.splitDownloader = null;
         }  
         else
            downloader.open("GET",this.spliturl+"&SPLIT=true&SPLIT_SESSION="+splitSession[1]+"&Data="+encode64(this.splitDownloader[this.splitDownloaderIndex]));
         downloader.send();
         return;
      }         
      if(!this.pendingFile)
      {
        this.pendingFile = true;
        this._cleanProgressBar();
        
        this._acquireFont(sender.ResponseText,
	                  SilverlightHelper.createDelegate(this, this._dynamicXPSHandleCompleted));
        return;
      } 
      this.pendingFile = null;          
      this.pendingCtrl.setFontSource(sender);
      this.pendingCtrl = null;
      this._cleanProgressBar();
   },
   _childWorker : function(parent,parseParent)
   {
      if(parseParent)
      {       
        var bindingData = new SilverlightHelper.FontBinding(parent,parent.tag);
        if(bindingData.bindingComplete)
        {
           this.bindingControls.length++;
           this.bindingControls[this.bindingControls.length-1] = bindingData;
        }
        else
          delete bindingData;
      }
      try
      {
         var temp = parent.children; 
      }
      catch(err)
      {
         return;
      }
      for(var i = 0; i < parent.children.count; i++)
          this._childWorker(parent.children.getItem(i),true);
   },
   _onDownloadProgressChanged : function(sender, eventArgs)
   {
      var percentage = Math.floor(sender.downloadProgress * 100);
      var progressText = sender.findName("progressText");
      var progressRectangle = sender.findName("progressRectangle");
      progressText.text = "Downloading Fonts "+percentage + "%";
      progressRectangle.width = percentage * 2; 
   },
   _createProgressBar : function(container)
   {     
      var xamlPercentage = "<Rectangle  Name='progressRectangle' Canvas.Left='20' Height='10' Width='0'  Fill='Blue' />";
      var xamlProgressText = "<TextBlock  Name='progressText'  Canvas.Top ='-4' Canvas.Left='230'	  Text='Downloading Fonts 0%' FontSize='12' />";
      var xamlProgressRectangle = "<Rectangle Name='progressContainer' Canvas.Top ='-1' Canvas.Left='19' Height='12' Width='202'  StrokeThickness='1' Stroke='Black' />";
      p1 = container.getHost().content.createFromXaml(xamlPercentage);
      p2 = container.getHost().content.createFromXaml(xamlProgressText);
      p3 = container.getHost().content.createFromXaml(xamlProgressRectangle);
      container.children.add(p1);
      container.children.add(p2);
      container.children.add(p3);
      this.progressContainer = container;
   },
   _cleanProgressBar : function()
   {
      if(this.progressContainer)
      {        
        var percentage = this.progressContainer.findName("progressContainer");
        var progressText = this.progressContainer.findName("progressText");
        var progressRectangle = this.progressContainer.findName("progressRectangle");      
        this.progressContainer.children.remove(percentage);
        this.progressContainer.children.remove(progressText);
        this.progressContainer.children.remove(progressRectangle);
        this.progressContainer = null;
      }  
   }
}

