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: forked from: wonderfl KeyVisual V.4.ja

Emotion Fractal in AS3
refer to http://levitated.net/daily/levEmotionFractal.html
// forked from hacker_ioo2xg0h's forked from: wonderfl KeyVisual V.4.ja
// 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_Black';
    private var fontNameBase:String = 'KozGoPro_Heavy';
   
    // for benchmark
    private var fontSwfBytesTotal:Number = 0;
        
    public function StringFractal() {
      stage.align = "TL";
      stage.scaleMode = "noScale";
      
      words = '北海道 青森 岩手 宮城 秋田 山形 福島 茨城 栃木 群馬 埼玉 千葉 東京 神奈川 新潟 富山 石川 福井 山梨 長野 岐阜 静岡 愛知 三重 滋賀 京都 大阪 兵庫 奈良 和歌山 鳥取 島根 岡山 広島 山口 徳島 香川 愛媛 高知 福岡 佐賀 長崎 熊本 大分 宮崎 鹿児島 沖縄'.split(' ');
      
      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 = -2;
      switch (stage.displayState) {
        case "fullScreen":
          tf.defaultTextFormat = new TextFormat(fontNameBase + '_5C00', 20, 0xffffff); // 小 5C0F
          tf.text = '小';
          break;
        case "normal":
        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;
    }
  }
}