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

青空文庫リーダー(※wonderfl上では動きません)

"Use Flash Player 10 text libraries (FTE).
*  You can do a lot of interesting things with text,
*  but I think it has even more potential
*  in experimental work where
*  the APIs are used just as a container format
*  for images, movie clips
*  and other interactive elements."
*                     by Justin Everett-Church
* 
* This code is an example of FTE.

なんちゃって青空文庫リーダー
* ※wonderfl上から青空文庫のサイトのデータを直接は読めません。
* ソースをダウンロードして、ローカルで動かしてみてください。
* 
* 縦書き半端です(─や…が横のまま)
* ルビは力技です(まともな方法を調べても全然見つからなかった…)
* 
* 全部一枚のSpriteに貼り付けてるので長い文章だと落ちます
* 
* Kenichi UENO(Keno)
Get Adobe Flash player
by keno42 24 Aug 2009
/**
 * Copyright keno42 ( http://wonderfl.net/user/keno42 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3uAc
 */

/**
 * 
 * "Use Flash Player 10 text libraries (FTE).
 *  You can do a lot of interesting things with text,
 *  but I think it has even more potential
 *  in experimental work where
 *  the APIs are used just as a container format
 *  for images, movie clips
 *  and other interactive elements."
 *                     by Justin Everett-Church
 * 
 * This code is an example of FTE.
 */

/**
 * なんちゃって青空文庫リーダー
 * ※wonderfl上から青空文庫のサイトのデータを直接は読めません。
 * ソースをダウンロードして、ローカルで動かしてみてください。
 * 
 * 縦書き半端です(─や…が横のまま)
 * ルビは力技です(まともな方法を調べても全然見つからなかった…)
 * 
 * 全部一枚のSpriteに貼り付けてるので長い文章だと落ちます
 * 
 * Kenichi UENO(Keno)
 */
 package {
    import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
    import flash.display.Sprite;
    import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.SecurityErrorEvent;
    import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
    import flash.system.System;
    import flash.text.engine.*;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	import flash.utils.ByteArray;
    
    [SWF(width = "465", height = "465", backgroundColor = "0xFFFFFF", fps = "30")]
    public class AdobeFTE extends Sprite {
        private var bookXML:XML;
        private var TEXT:String = "Use Flash Player 10 text libraries (FTE).  You can do a lot of interesting things with text, but I think it has even more potential in experimental work where the APIs are used just as a container format for images, movie clips and other interactive elements.";
		private var textArray:Array;
		private var textReadingArray:Array;
		private var ns:String;
		private var tx:Number = 0;
		private var ty:Number = 0;
		private var paper:Sprite = new Sprite();
		
        public function AdobeFTE() {
			var tf:TextField = new TextField();
			tf.type = "input";
			tf.text = "http://www.aozora.gr.jp/cards/000879/files/3814_27290.html";
			tf.autoSize = "left";
			tf.border = true;
			tf.addEventListener(KeyboardEvent.KEY_DOWN, onTfKeyDown);
			
			this.addChild( tf );
			this.addChild( paper );
			
			load(tf.text);
		}
		protected function onTfKeyDown(e:KeyboardEvent):void {
			if ( e.keyCode == Keyboard.ENTER ) {
				load( e.target.text );
			}
		}
		protected function load(url:String):void {
			// init
			while ( paper.numChildren ) paper.removeChildAt(0);
			paper.x = paper.y = 0;
			offsetX = 425;
			offsetY = 32;
			
			var urlLoader:URLLoader = new URLLoader();
			urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			urlLoader.addEventListener(Event.COMPLETE, onComplete);
			urlLoader.dataFormat = URLLoaderDataFormat.BINARY; 
			urlLoader.load(new URLRequest(url));
        }
		protected function onSecurityError(e:SecurityErrorEvent):void {
			trace(e);
		}
        protected function onComplete(e:Event):void {
			// load as binary and read by shift_jis encoding
			var byteData:ByteArray = ByteArray(e.target.data);
			bookXML = new XML(byteData.readMultiByte(byteData.length, "shift_jis"));
			ns = bookXML.namespaceDeclarations().toString();
			default xml namespace = new Namespace(ns);
			
			TEXT = bookXML.body.toString();
			TEXT = TEXT.replace(/ /g, "");
			TEXT = TEXT.replace(/(\r|\n)/g, "");
			TEXT = TEXT.split(/<\/h[12]>/g).join("\n");
			TEXT = TEXT.split(/<br\/>/g).join("\n");
			textArray = TEXT.split("\n");
			for ( var i:int = 0; i < textArray.length; i++ ) {
				var array:Array = [];
				var temp:String = textArray[i];
				var matchArray:Array = temp.match(/<rt>([^<\/]*)<\/rt/g);
				var tempArray:Array = temp.split("<ruby><rb>");
				for ( var j:int = 0; j < tempArray.length; j++ ) {
					if ( j > 0 ) {
						array.push( matchArray[j - 1].substr(4, matchArray[j - 1].length - 8) );
					}
					tempArray[j] = tempArray[j].replace(/<rp>.*<\/ruby>/g, "");
					tempArray[j] = tempArray[j].replace(/<[^>]*>/g, "");
					array.push( tempArray[j] );
				}
				textArray[i] = array;
			}
            setup();
		}
        private function setup():void {
			
			for ( var i:int = 0; i < textArray.length; i++ ) {
				var tempText:String = "";
				var tempSp:Sprite = new Sprite();
				for ( var j:int = 0; j < textArray[i].length; j++ ) {
					if ( j & 1 ) {
//						this.graphics.drawCircle(lastX, lastY, j + 1); // debug
						var ruby:TextLine = createTextBlock( createContentElement( textArray[i][j], createElementFormat( fontDescription, true ) ), textJustifier ).createTextLine(null, 100);
						paper.addChild( ruby );
						ruby.x = lastX;
						if ( lastY != offsetY && (tempText.substr( -1, 1) == "、" || tempText.substr( -1, 1) == "。") ) {
							lastY += 8;
						}
						ruby.y = lastY;
						
					} else {
						if ( textArray[i][j] == "" ) textArray[i][j] = " ";
						tempText += textArray[i][j];
						// FontDescription : フォント設定
						var fontDescription:FontDescription = createFontDescription();
						
						// ElementFormat 
						var elementFormat:ElementFormat = createElementFormat( fontDescription );

						//  ContentElement
						var contentElement: ContentElement = createContentElement( tempText, elementFormat );
						
						// TextJustifier
						var textJustifier:TextJustifier =createTextJustifier();
						
						//  TextBlock
						var textBlock:TextBlock = createTextBlock( contentElement, textJustifier );
						
						if( j < textArray[i].length-1 ){
							layout( textBlock, tempSp );
						} else {
							layout( textBlock, paper );
						}
					}
				}
			}
			tempSp = null;
			this.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
		private function onKeyDown(e:KeyboardEvent):void {
			switch( e.keyCode ) {
				case Keyboard.LEFT:
						tx += 35;
						if ( tx > (paper.width - 300 )) tx -= 35;
					break;
				case Keyboard.RIGHT:
						tx -= 35;
						if ( tx < -80 ) tx += 35;
					break;
				case Keyboard.DOWN:
						tx += 400;
						if ( tx > (paper.width - 300 )) tx = (paper.width - 300 );
					break;
				case Keyboard.UP:
						tx -= 400;
						if ( tx < -80 ) tx = -80;
					break;
			}
		}
		private function onEnterFrame(e:Event):void {
			paper.x += ( tx - paper.x ) * 0.25;
			paper.y += ( ty - paper.y ) * 0.25;
		}
        private var offsetX:int = 425;
		private var offsetY:int = 32;
		private var lastX:int;
		private var lastY:int;
		private var lineWidth:Number=2.5;
        private function layout(textBlock:TextBlock, output:DisplayObjectContainer):void {
			if ( output != paper ) {
				var oldOffsetX:int = offsetX;
				var oldOffsetY:int = offsetY;
			}
            var textLine:TextLine = textBlock.createTextLine ( null, 400 );
//			this.graphics.lineStyle(0, 0xFF0000);
//			this.graphics.drawCircle(offsetX, offsetY, 2); // debug
            while (textLine) {
                output.addChild(textLine);
                textLine.x = offsetX;
                textLine.y = offsetY;
				this.graphics.drawRect(offsetX, offsetY, textLine.width, textLine.height); // debug
				lastX = offsetX + textLine.width;
				lastY = offsetY + textLine.height;
				if ( lastY >= 425 ) { // やっつけ
					lastX -= textLine.textHeight * lineWidth;
					lastY = offsetY;
				}
				offsetX -= textLine.textHeight * lineWidth;
				textLine = textBlock.createTextLine( textLine, 400 );
            }
			if ( output != paper ) {
				offsetX = oldOffsetX;
				offsetY = oldOffsetY;
			}
        }
        
        
        // FontDescription : フォント設定
        private function createFontDescription():FontDescription {
            var fontDescription :FontDescription = new FontDescription();
            // CFFHinting.NONE, // CFFHinting.HORIZONTAL_STEM
            fontDescription.cffHinting = CFFHinting.HORIZONTAL_STEM;
            // FontLookup.DEVICE, FontLookup.EMBEDDED_CFF
            fontDescription.fontLookup = FontLookup.DEVICE;
            //_ゴシック, 明朝, _等幅, _sans, _serif, _typewriter
            fontDescription.fontName = "明朝, _sans";
            // FontPosture.NORMAL, FontPosture.ITALIC
            fontDescription.fontPosture = FontPosture.NORMAL;
            // FontWeight.NORMAL, FontWeight.BOLD
            fontDescription.fontWeight = FontWeight.NORMAL;
            // true, false
            fontDescription.locked = false;
            // RenderingMode.NORMAL, RenderingMode.CFF
            fontDescription.renderingMode = RenderingMode.CFF;
            return fontDescription;
        }
        
        
        // ElementFormat : テキストフォーマット設定
        private function createElementFormat( fontDescription:FontDescription, isRuby:Boolean = false  ):ElementFormat {
            var elementFormat:ElementFormat = new ElementFormat();
            // TextBaseline.ROMAN, TextBaseline.ASCENT, TextBaseline.DESCENT, TextBaseline.IDEOGRAPHIC_TOP, TextBaseline.IDEOGRAPHIC_CENTER, TextBaseline.IDEOGRAPHIC_BOTTOM
            elementFormat.alignmentBaseline = TextBaseline.ROMAN;
            // Number
            elementFormat.alpha = 1;
            // Number
            elementFormat.baselineShift = 0;
            // BreakOpportunity.AUTO, BreakOpportunity.ANY, BreakOpportunity.NONE, BreakOpportunity.ALL
            elementFormat.breakOpportunity = BreakOpportunity.AUTO;
            // uint
            elementFormat.color = 0x000000;
            // DigitCase.DEFAULT, DigitCase.LINING, DigitCase.OLD_STYLE
            elementFormat.digitCase = DigitCase.DEFAULT;
            // DigitWidth.DEFAULT, DigitWidth.PROPORTIONAL, DigitWidth.TABULAR
            elementFormat.digitWidth = DigitWidth.TABULAR;
           // TextBaseline.ROMAN, TextBaseline.ASCENT, TextBaseline.DESCENT, TextBaseline.IDEOGRAPHIC_TOP, TextBaseline.IDEOGRAPHIC_CENTER, TextBaseline.IDEOGRAPHIC_BOTTOM
            elementFormat.dominantBaseline = TextBaseline.ROMAN;
            // FontDescription
            elementFormat.fontDescription = fontDescription;
            // Number
            elementFormat.fontSize = isRuby?8: 15;
            // Kerning.ON, Kerning.OFF, Kerning.AUTO
            elementFormat.kerning= Kerning.ON;
            // LigatureLevel.NONE, LigatureLevel.MINIMUM, LigatureLevel.COMMON, LigatureLevel.UNCOMMON, LigatureLevel.EXOTIC
            elementFormat.ligatureLevel = LigatureLevel.NONE;
            // String
            elementFormat.locale = "ja";
            // true, false
            elementFormat.locked= false;
            // TextRotation.ROTATE_0, TextRotation.ROTATE_90, TextRotation.ROTATE_180, TextRotation.ROTATE_270, TextRotation.AUTO
            elementFormat.textRotation = TextRotation.ROTATE_270;
            // Number
            elementFormat.trackingLeft = 0;
            // Number
            elementFormat.trackingRight = 0;
            // TypographicCase.DEFAULT, TypographicCase.TITLE, TypographicCase.CAPS, TypographicCase.SMALL_CAPS, TypographicCase.UPPERCASE, TypographicCase.LOWERCASE, TypographicCase.CAPS_AND_SMALL_CAPS
            elementFormat.typographicCase= TypographicCase.DEFAULT;
            
            return elementFormat;
        }
        
        
        // ContentElement : 表示内容
        private function createContentElement( content:*, elementFormat:ElementFormat ):ContentElement {
            // GraphicElement, GroupElement, TextElement
            var contentElement: ContentElement = new TextElement();
            
            //var graphicElement: GraphicElement= new GraphicElement();
            //var groupElement: GroupElement= new GroupElement();
            
            // ElementFormat
            contentElement.elementFormat = elementFormat;
            // EventDispatcher, 
            contentElement.eventMirror = null;
            // GroupElement
            contentElement.groupElement;// read-only
            // String
            contentElement.rawText;// read-only
            // String
            contentElement.text; // read-only
            // TextBlock
            contentElement.textBlock;// read-only
            // int
            contentElement.textBlockBeginIndex;// read-only
            // TextRotation.ROTATE_0, TextRotation.ROTATE_90, TextRotation.ROTATE_180, TextRotation.ROTATE_270, TextRotation.AUTO
            contentElement.textRotation = TextRotation.ROTATE_0;
            // *
            contentElement.userData;
            
            // for SubClass's elements
            switch( true ) {
                case contentElement is TextElement:
                    var textElement: TextElement = contentElement as TextElement;
                    var str:String = content as String;
                    textElement.text = str;
                break;
                case contentElement is GraphicElement:
                    var graphicElement: GraphicElement= contentElement as GraphicElement;
                    var display:DisplayObject = content as DisplayObject;
                    graphicElement.elementWidth = display.width;
                    graphicElement.elementHeight = display.height;
                    graphicElement.graphic= display;
                break;
                case contentElement is GroupElement:
                    var groupElement: GroupElement= contentElement as GroupElement;
                    groupElement.elementCount; // read-only
                    // getElementAt( index:int ):ContentElement;
                    // getElementAtCharIndex( charIndex:int ):ContentElement;
                    // mergeTextElements( element:ContentElement ):int;
                    // groupElements( beginIndex:int, endIndex:int ):GroupElement;
                    // replaceElements( beginIndex:int, endIndex:int ):TextElement;
                    //  setElements( value:Vector.<ContentElement> ):void;
                    // splitTextElement( elementIndex:int, splitIndex:int ):TextElement;
                    // ungroupElements( groupIndex:int ):void;
                break;
            }
            
            return textElement;
        }
        
        
        // TextJustifier : 整列設定
        private function createTextJustifier():TextJustifier {
            // EastAsianJustifier, SpaceJustifier, 
            var textJustifier:TextJustifier = new EastAsianJustifier("ja");
            // var textJustifier:TextJustifier = new SpaceJustifier("ja");
            // LineJustification.UNJUSTIFIED, LineJustification.ALL_BUT_LAST, LineJustification.ALL_INCLUDING_LAST
            textJustifier.lineJustification = LineJustification.UNJUSTIFIED;
            
            switch( true ) {
                case textJustifier is EastAsianJustifier:
                    var eastAsianJustifier:EastAsianJustifier = textJustifier as EastAsianJustifier;
                    // JustificationStyle.PUSH_IN_KINSOKU, JustificationStyle.PUSH_OUT_ONLY, JustificationStyle.PRIORITIZE_LEAST_ADJUSTMENT
                    eastAsianJustifier.justificationStyle = JustificationStyle.PUSH_IN_KINSOKU;
                break;
                case textJustifier is SpaceJustifier:
                    var spaceJustifier:SpaceJustifier= textJustifier as SpaceJustifier;
                    // true , false
                    spaceJustifier.letterSpacing  = true;
                break;
            }
            return textJustifier;
        }
        
        
        // TextBlock : 段組設定
        private function createTextBlock( content:ContentElement, textJustifier:TextJustifier ):TextBlock {
            var textBlock:TextBlock = new TextBlock();
            // true, false
            textBlock.applyNonLinearFontScaling = true;
            // FontDescription
            textBlock.baselineFontDescription;
            // Number
            textBlock.baselineFontSize = 24;
            // TextBaseline.ROMAN, TextBaseline.ASCENT, TextBaseline.DESCENT, TextBaseline.IDEOGRAPHIC_TOP, TextBaseline.IDEOGRAPHIC_CENTER, TextBaseline.IDEOGRAPHIC_BOTTOM
            textBlock.baselineZero = TextBaseline.ROMAN;
            // int
            textBlock.bidiLevel 
            // TextElement, GraphicElement, GroupElement 
            textBlock.content = content;
            // TextLine 
            textBlock.firstInvalidLine; // read-only
            // TextLine 
            textBlock.firstLine; // read-only
            // TextLine 
            textBlock.lastLine; // read-only
            // TextRotation.ROTATE_0, TextRotation.ROTATE_90, TextRotation.ROTATE_180, TextRotation.ROTATE_270, TextRotation.AUTO
            textBlock.lineRotation = TextRotation.ROTATE_90;
            // Vector.<TabStop> 
            textBlock.tabStops;
            // EastAsianJustifier, SpaceJustifier, 
            textBlock.textJustifier = textJustifier;
            // TextLineCreationResult.SUCCESS, TextLineCreationResult.COMPLETE, TextLineCreationResult.INSUFFICIENT_WIDTH
            textBlock.textLineCreationResult// read-only
            // *
            textBlock.userData;
            
            return textBlock;
        }
        
    }
}