In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: Hirakana Fractal in AS3

Emotion Fractal in AS3
refer to http://levitated.net/daily/levEmotionFractal.html
// forked from ht_tregra's Hirakana Fractal in AS3
// Emotion Fractal in AS3
// refer to http://levitated.net/daily/levEmotionFractal.html

package {
  import flash.display.Loader;  
  import flash.display.Sprite;
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.events.IOErrorEvent;
  
  import flash.net.URLRequest; 
  import flash.net.URLLoader;

  import flash.geom.Rectangle;
  import flash.geom.ColorTransform;
  
  import flash.text.*;
  
  import caurina.transitions.Tweener;
  import caurina.transitions.properties.TextShortcuts;

  import flash.system.System;
  import flash.system.Security;
  import flash.system.ApplicationDomain;
  import flash.system.SecurityDomain;
  import flash.system.LoaderContext;

  [SWF(backgroundColor="#000000", frameRate=30)] 

  public class StringFractal extends Sprite {
    
    private var holder:Sprite;
    
    private var queue:Array;
    private var words:Array;
    private var colors:Array;
    
    private var font:Class;
    
    private var fontCache:Array = [];
    private var fontLoaded:Number = 0;
    private var fontTotal:Number = 0;
    
    //private var fontNameBase:String = 'Mplus_2c_Thin';
    private var fontNameBase:String = 'KozMinPro_ExtraLight';
    
    // for benchmark
    private var fontSwfBytesTotal:Number = 0;
        
    public function StringFractal() {
      stage.align = "TL";
      stage.scaleMode = "noScale";
      
      words = [];
      for (var i:int = 0x3041;i < 0x3095;i++) {
        words.push( String.fromCharCode(i) );  
      }
      
      holder = new Sprite();
      addChild(holder);
      
      TextShortcuts.init();
      
      prepareFont();
    }

    private function onclick( e :MouseEvent ):void {
      switch (stage.displayState) {
        case "normal" :
          stage.displayState = "fullScreen";
          break;
        case "fullScreen" :
          default :
          stage.displayState = "normal";
          break;
      }
      init(null);
    }

    public function init(e:MouseEvent):void {
      Tweener.removeAllTweens();
      
      while (holder.numChildren) holder.removeChildAt(0);
      queue = [new Rectangle(0, 0, stage.stageWidth, stage.stageHeight)];
      colors = [0xffffff, Math.ceil(Math.random()*0xffffff)];
      
      // フルスクリーン用ボタン
      var oldBtn:Sprite = getChildByName('fullscreen_btn') as Sprite;
      if (oldBtn) {
        removeChild( oldBtn );
        oldBtn = null;
      }

      var btn :Sprite = new Sprite;
      addChild( btn );
      btn.name = 'fullscreen_btn';
      btn.alpha = 0.8;
      btn.graphics.beginFill(colors[1]);
      btn.graphics.drawRect(0,0,25,25);
      btn.buttonMode = true;
      var tf: TextField = new TextField();
      tf.selectable = false;
      tf.embedFonts = true;
      tf.y = -3;
      switch (stage.displayState) {
        case "fullScreen":
          tf.defaultTextFormat = new TextFormat(fontNameBase + '_5C00', 20, 0xffffff); // 小 5C0F
          tf.text = '小';
          break;
        case "fullScreen":
        default:
          tf.defaultTextFormat = new TextFormat(fontNameBase + '_5900', 20, 0xffffff); // 大 5927
          tf.text = '大';
          break;
      }
      btn.addChild(tf);
      btn.addEventListener( MouseEvent.CLICK, onclick );

      addEventListener(Event.ENTER_FRAME, fill);
    }
    
    public function prepareFont():void {
      
      loadFontForString();
    
    }
    
    public function loadFontForString():void {
      var str:String = words.join();
      str += '大小'; // フルスクリーンボタン用

      var str_len:int = str.length;
      for (var i:int = 0;i < str_len;i++) {
        var charCode:String = NumberToString( str.charCodeAt(i) );
        
        while (charCode.length < 4) {
          charCode = '0' + charCode;
        }
        
        var fontName:String = fontNameBase + '_' + charCode.charAt(0) + charCode.charAt(1) + '00';
        
        var insert:Boolean = true;
        for (var j:int = 0;j < fontCache.length;j++) {
          if (fontCache[j] == fontName) {
            insert = false;
          }
        }
        if (insert) {
          loadFontSwf("http://www.tregra.jp/as3/font/"+fontName+".swf");
          //loadFontSwf("../../as3/font/"+fontName+".swf");
          fontCache.push(fontName);
          fontTotal++;
        }
      }
    }
    
    private function loadFontSwf(url:String):void {
      var ldr:Loader = new Loader();
      var ldr_context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, SecurityDomain.currentDomain);
      
      ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, fontSwfLoaded);
      ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, fontSwfLoadIOError);
      
      ldr.load(new URLRequest(url), ldr_context);
    }
    
    private function fontSwfLoadIOError(event:Event):void {
      fontLoaded++;
    }
    
    private function fontSwfLoaded(event:Event):void {
      var url:String = event.target.url;
      
      var fontName:String = fontNameBase + url.match(/_[0-9a-fA-F]{2}00/);
      
      fontSwfBytesTotal += event.target.bytesTotal;
      
      //var FontLibrary:Class = ApplicationDomain.currentDomain.getDefinition(fontName) as Class;
      var FontLibrary:Class = event.target.applicationDomain.getDefinition(fontName) as Class;
      Font.registerFont(FontLibrary[fontName]);
      
      fontLoaded++;
      
      if (fontLoaded == fontTotal) { // フォント読み込み完了
        init(null);
        holder.addEventListener(MouseEvent.MOUSE_DOWN, init);
      }
    }
    
    public function fill(e:Event):void {
      var i:int = 0;
      
      while (queue.length > 0 && i < 3) {
        var rect:Rectangle = queue.pop();
        if (rect.width > 2 && rect.height > 2) {
          fillRegion(rect);
          i++;
        }
      }
      
      if (!queue.length) removeEventListener(Event.ENTER_FRAME, fill);
    }
    
    public function fillRegion(region:Rectangle):void {
      var tf:TextField = new TextField();
      var fmt:TextFormat = new TextFormat();
      var str:String = choice(words);
      
      // glyph check :p
      var hasGlyphs:Boolean = false;
      var fonts:Array = Font.enumerateFonts();
      
      while (! hasGlyphs) {
        for ( var str_i:int = 0;str_i < str.length;str_i++) {
          var hasGlyph:Boolean = false;
          for ( var font_i:String in fonts) {
            if (fonts[font_i].hasGlyphs(str.charAt(str_i))) {
              hasGlyph = true;
            }
          }
          hasGlyphs = hasGlyph;
        }
        if (! hasGlyphs) str = choice(words);
      }

      fmt.size = 24;
      fmt.letterSpacing = -0.4;
      fmt.rightMargin = 0.4;
      
      tf.text = str;
      tf.autoSize = TextFormatAlign.LEFT;
      tf.embedFonts = true;
      tf.gridFitType = GridFitType.PIXEL;
      tf.selectable = false;
      
      for (var i:int = 0;i < str.length;i++) {
        var charCode:String = NumberToString( str.charCodeAt(i) );
        
        while ( charCode.length < 4 ) {
          charCode = '0' + charCode;
        }
        
        var fontName:String = fontNameBase + '_' + charCode.charAt(0) + charCode.charAt(1) + '00';
        fmt.font = fontName;
        
        tf.setTextFormat(fmt, i);
      }
      
      var bitmap:BitmapData = new BitmapData(tf.width, tf.height, true);
      bitmap.draw(tf);
      var bound:Rectangle = bitmap.getColorBoundsRect(0xFFFFFFFF, 0xFFFFFFFF, false);
      bitmap.dispose();
      
      var s:Number = region.width / bound.width * (Math.random() * 0.4 + 0.1);
      if (bound.height * s > region.height) s = region.height / bound.height;
      tf.scaleX = s;
      tf.scaleY = s;
      
      bound.x *= s;
      bound.y *= s;
      bound.width  *= s;
      bound.height *= s;
      
      switch (choice([1,2,3,4])) {
        case 1:
          tf.x = region.x - bound.x;
          tf.y = region.y - bound.y;
          queue.push(
            new Rectangle(region.x + bound.width, region.y, region.width - bound.width, bound.height),
            new Rectangle(region.x, region.y + bound.height, region.width, region.height - bound.height)
          );
          break;
        case 2:
          tf.x = region.x - bound.x;
          tf.y = region.bottom - bound.bottom;
          queue.push(
            new Rectangle(region.x + bound.width, region.bottom - bound.height, region.width - bound.width, bound.height),
            new Rectangle(region.x, region.y, region.width, region.height - bound.height)
          );
          break;
        case 3:
          tf.x = region.right - bound.right;
          tf.y = region.y - bound.y;
          queue.push(
            new Rectangle(region.x, region.y, region.width - bound.width, bound.height),
            new Rectangle(region.x, region.y + bound.height, region.width, region.height - bound.height)
          );
          break;
        case 4:
          tf.x = region.right - bound.right;
          tf.y = region.bottom - bound.bottom;
          queue.push(
            new Rectangle(region.x, region.bottom - bound.height, region.width - bound.width, bound.height),
            new Rectangle(region.x, region.y, region.width, region.height - bound.height)
          );
          break;
      }

      holder.addChild(tf);
      
      Tweener.addTween(tf, {_text_color: choice(colors), time: 5, transition: "liner"});
    }
    
    private function choice(ary:Array):* {
      return ary[Math.floor(ary.length * Math.random())];
    }
    
    // code from Copyright (c) 2008 Spark project  (www.libspark.org) 
    // org.libspark.utils.BaseUtil
    
    /**

     * 数値を文字列に変換します。
     * numberが127で、dictionaryが"0123456789ABCDEF"(デフォルト)の場合、"7F"を返します。
     * @author  Kenichi Ueno
     * @param  number: 数値に変換したい文字列
     * @param  dictionary: 辞書になる文字列("."は小数点として扱うので使えません)
     * @param  maxDisplayDigitNumber: 小数点以下の最大桁数
     * @return  numberをdictionaryを基底として表した文字列を返します。
     */

    static public function NumberToString(number:Number, dictionary:String = "0123456789ABCDEF", maxDisplayUnderPoint:int = 10):String
    {
      var _base:Number = dictionary.length;
      var _divideNum:Number;
      var _dictionary:Array = new Array(_base);
      var _i:int;
      var _ret:String = "";
      var _digitNumber:Number;
      var _tempNum:Number;
      var _digitCount:int = maxDisplayUnderPoint;
      for ( _i = 0; _i < _base; _i++ )
      {
        _dictionary[_i] = dictionary.charCodeAt(_i);
      }
      if ( number == 0 )
      {
        return String.fromCharCode(_dictionary[0]);
      } else {
        _digitNumber = Math.floor( Math.log(number) / Math.log(_base) ); // 最大桁数
      }
      _divideNum = Math.pow( _base, _digitNumber );
      if ( _digitNumber < 0 )
      {
        _ret += String.fromCharCode(_dictionary[0]);
      }
      while ( (number > 0) && (maxDisplayUnderPoint != (++_digitCount) ) )
      {
        if ( _digitNumber-- == -1 )
        {
          _ret += ".";
          _digitCount = 0;
        }
        _tempNum = Math.floor(number / _divideNum);
        _ret += String.fromCharCode(_dictionary[_tempNum]);
        number %= _divideNum;
        number *= _base;
      }
      while ( _digitNumber-- >= 0 )
      {
        _ret += String.fromCharCode(_dictionary[0]);
      }
      return _ret;
    }
  }
}