diff --git a/.gitmodules b/.gitmodules index cbdda48..ef32953 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,3 @@ [submodule "lib/jasmine-haxe"] path = lib/jasmine-haxe url = git://github.com/rjanicek/jasmine-haxe.git -[submodule "lib/janicek-core-haxe"] - path = lib/janicek-core-haxe - url = git://github.com/rjanicek/janicek-core-haxe.git -[submodule "lib/html5-haxe"] - path = lib/html5-haxe - url = git://github.com/rjanicek/html5-haxe.git diff --git a/bin/index.css b/bin/index.css new file mode 100644 index 0000000..5cf5648 --- /dev/null +++ b/bin/index.css @@ -0,0 +1,39 @@ +body { margin:0; padding:0; } + +canvas { position: absolute; } + +fieldset { + position:absolute; + top:10px; + left:10px; + padding-top:10px; + font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; + background:#C38EC7; + -moz-border-radius:5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +label { + clear: both; + display: block; + width: 125px; + float: left; +} + +input[type=text], input[type=file], input[type=range] { width: 110px; } + +input[type=file] { color: #C38EC7; } + +input[type=range] { border-bottom-left-radius: 5px; } + +#seed,#shapeSeed { width: 50px; } + +img { width: 110px; } + +.section { margin-top: 10px; } + +.hide { display: none; } + +.timer { display: inline-block; text-align: right; width: 40px; } +.total { border-top: solid 1px black; } \ No newline at end of file diff --git a/bin/index.html b/bin/index.html index 53e82fc..de06af1 100644 --- a/bin/index.html +++ b/bin/index.html @@ -1,65 +1,20 @@ - - + + voronoi-map-haxe - - - - + + + - + +
voronoi-map-haxe

source code on GitHub

-
+
-
+
-
-
+
+
@@ -105,6 +60,10 @@
+
+
0
ms
+
0
ms
+
0
ms
hide
diff --git a/build-test.hxml b/build-test.hxml index f39fee0..b795f03 100644 --- a/build-test.hxml +++ b/build-test.hxml @@ -1,7 +1,8 @@ -cp test/src -cp src --cp lib/janicek-core-haxe/src +-cp lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src -cp lib/jasmine-haxe/src -js test/bin/voronoi-map-test.js -main Main --debug \ No newline at end of file +-debug +-D js-classic \ No newline at end of file diff --git a/build.hxml b/build.hxml index 8132ef7..6ef9625 100644 --- a/build.hxml +++ b/build.hxml @@ -3,6 +3,5 @@ -cp lib/html5-haxe -js bin/voronoi-map.js -main voronoimap.Main ---js-modern ---dead-code-elimination +-dce full -debug \ No newline at end of file diff --git a/lib/html5-haxe b/lib/html5-haxe deleted file mode 160000 index 7423e2b..0000000 --- a/lib/html5-haxe +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7423e2b0990c7948fc239d7e3fc78c892c272114 diff --git a/lib/html5-haxe/README b/lib/html5-haxe/README new file mode 100644 index 0000000..71f38f0 --- /dev/null +++ b/lib/html5-haxe/README @@ -0,0 +1,25 @@ + +html5-haxe +========== +HaXe/Javascript html5 typedef signatures not available in the haXe std library. + +Tested with haXe 2.07 and Chrome. + +html5 - haXe html5 bindings. +html5Test - Jasmine specs for html5. + +LINKS +----- +https://github.com/tong/hx.html5 + +http://www.w3.org/TR/html5/ + +https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html + +http://www.w3.org/TR/webstorage/ +http://www.w3.org/TR/file-system-api/ +http://dev.w3.org/geo/api/ +https://developer.mozilla.org/En/E4X/Processing_XML_with_E4X + +http://www.webrtc.org/ +http://dev.w3.org/2011/webrtc/editor/webrtc.html diff --git a/lib/html5-haxe/haxelib.xml b/lib/html5-haxe/haxelib.xml new file mode 100644 index 0000000..89451a0 --- /dev/null +++ b/lib/html5-haxe/haxelib.xml @@ -0,0 +1,5 @@ + + + Javascript html5 typedef signatures + Misc + \ No newline at end of file diff --git a/lib/html5-haxe/html5/ApplicationCache.hx b/lib/html5-haxe/html5/ApplicationCache.hx new file mode 100644 index 0000000..8a49bb8 --- /dev/null +++ b/lib/html5-haxe/html5/ApplicationCache.hx @@ -0,0 +1,31 @@ +package html5; + +/** + Create instance: var cache : ApplicationCache = untyped window.applicationCache; +*/ +@:native("window.applicationCache") extern class ApplicationCache { + + static var UNCACHED(default,null) : Int; + static var IDLE(default,null) : Int; + static var CHECKING(default,null) : Int; + static var DOWNLOADING(default,null) : Int; + static var UPDATEREADY(default,null) : Int; + static var OBSOLETE(default,null) : Int; + + var onchecking : Void->Void; + var onerror : Void->Void; + var onnoupdate : Void->Void; + var ondownloading : Void->Void; + var onprogress : Void->Void; + var onupdateready : Void->Void; + var oncached : Void->Void; + var onobsolete : Void->Void; + + var status(default,null) : Int; + //var status(default,null) : ApplicationCacheStatus; + + function update() : Void; + function abort() : Void; + function swapCache() : Void; + +} diff --git a/lib/html5-haxe/html5/Audio.hx b/lib/html5-haxe/html5/Audio.hx new file mode 100644 index 0000000..4312cd4 --- /dev/null +++ b/lib/html5-haxe/html5/Audio.hx @@ -0,0 +1,6 @@ +package html5; +//http://www.w3.org/TR/html5/video.html#audio + +extern class Audio extends HTMLMediaElement { + function new( ?src : String ) : Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/Blob.hx b/lib/html5-haxe/html5/Blob.hx new file mode 100644 index 0000000..893e7b2 --- /dev/null +++ b/lib/html5-haxe/html5/Blob.hx @@ -0,0 +1,8 @@ +package html5; + +@:native("Blob") +extern class Blob { + var size(default,null) : Float; + var type(default,null) : String; + function slice( start : Int, length : Int, ?contentType : String ) : Blob; +} diff --git a/lib/html5-haxe/html5/BlobBuilder.hx b/lib/html5-haxe/html5/BlobBuilder.hx new file mode 100644 index 0000000..28d26b2 --- /dev/null +++ b/lib/html5-haxe/html5/BlobBuilder.hx @@ -0,0 +1,11 @@ +package html5; + +//TODO +//extern class BlobBuilder { +@:native("window.WebKitBlobBuilder") extern class BlobBuilder { + function new() : Void; + @:overload(function(data:ArrayBuffer):Void{}) + @:overload(function(data:Blob):Void{}) + function append( data : String, ?endings : String ) : Void; + function getBlob( ?contentType : String ) : Blob; +} diff --git a/lib/html5-haxe/html5/Canvas.hx b/lib/html5-haxe/html5/Canvas.hx new file mode 100644 index 0000000..0ed8f7b --- /dev/null +++ b/lib/html5-haxe/html5/Canvas.hx @@ -0,0 +1,10 @@ +package html5; +import js.html.CanvasElement; + +typedef Canvas = { >CanvasElement, + var width : Int; + var height : Int; + function getContext( id : String ) : CanvasRenderingContext2D; + //DOMString toDataURL(optional in DOMString type, in any... args); + function toDataURL( ?mimetype : String ) : String; +} diff --git a/lib/html5-haxe/html5/CanvasGradient.hx b/lib/html5-haxe/html5/CanvasGradient.hx new file mode 100644 index 0000000..faf38e8 --- /dev/null +++ b/lib/html5-haxe/html5/CanvasGradient.hx @@ -0,0 +1,5 @@ +package html5; + +typedef CanvasGradient = { + function addColorStop( offset : Float, color : String ) : Void; +} diff --git a/lib/html5-haxe/html5/CanvasPattern.hx b/lib/html5-haxe/html5/CanvasPattern.hx new file mode 100644 index 0000000..4abd908 --- /dev/null +++ b/lib/html5-haxe/html5/CanvasPattern.hx @@ -0,0 +1,4 @@ +package html5; + +typedef CanvasPattern = { +} diff --git a/lib/html5-haxe/html5/CanvasPixelArray.hx b/lib/html5-haxe/html5/CanvasPixelArray.hx new file mode 100644 index 0000000..bdd0e02 --- /dev/null +++ b/lib/html5-haxe/html5/CanvasPixelArray.hx @@ -0,0 +1,5 @@ +package html5; + +extern class CanvasPixelArray implements ArrayAccess { + var length : Int; +} diff --git a/lib/html5-haxe/html5/CanvasRenderingContext2D.hx b/lib/html5-haxe/html5/CanvasRenderingContext2D.hx new file mode 100644 index 0000000..5612d1d --- /dev/null +++ b/lib/html5-haxe/html5/CanvasRenderingContext2D.hx @@ -0,0 +1,92 @@ +package html5; + +typedef CanvasRenderingContext2D = { + + // back-reference to the canvas + var canvas(default,null) : Canvas; + + // state + function save() : Void; + function restore() : Void; + + // transformations (default transform is the identity matrix) + function scale( x : Float, y : Float ) : Void; + function rotate( angle : Float ) : Void; + function translate( x : Float, y : Float ) : Void; + function transform( m11 : Float, m12 : Float, m21 : Float, m22 : Float, dx : Float, dy : Float ) : Void; + function setTransform( m11 : Float, m12 : Float, m21 : Float, m22 : Float, dx : Float, dy : Float ) : Void; + function rect( x : Float, y : Float, width : Float, height : Float ) : Void; + + // compositing + var globalAlpha : Float; + var globalCompositeOperation : String; + + // colors and styles + var strokeStyle : Dynamic; + var fillStyle : Dynamic; + function createLinearGradient( x0 : Float, y0 : Float, x1 : Float, y1 : Float ) : CanvasGradient; + function createRadialGradient( x0 : Float, y0 : Float, r0 : Float, x1 : Float, y1 : Float, r1 : Float ) : CanvasGradient; + @:overload(function (image:HTMLVideoElement,repetition:String):Void{}) + @:overload(function (image:Canvas,repetition:String):Void{}) + function createPattern( image : Image, repetition : String ) : Void; + + // line caps/joins + var lineWidth : Float; + var lineCap : String; + var lineJoin : String; + var miterLimit : Float; + + // shadows + var shadowOffsetX : Float; + var shadowOffsetY : Float; + var shadowBlur : Float; + var shadowColor : String; + + // rects + function clearRect( x : Int, y : Int, w : Int, h : Int ) : Void; + function fillRect( x : Int, y : Int, w : Int, h : Int ) : Void; + function strokeRect( x : Int, y : Int, w : Int, h : Int ) : Void; + + // path API + function beginPath() : Void; + function closePath() : Void; + function moveTo( x : Float, y : Float ) : Void; + function lineTo( x : Float, y : Float ) : Void; + function quadraticCurveTo( cpx : Float, cpy : Float, x : Float, y : Float ) : Void; + function bezierCurveTo( cp1x : Float, cp1y : Float, cp2x : Float, cp2y : Float, x : Float, y : Float ) : Void; + function arcTo( x1 : Float, y1 : Float, x2 : Float, y2 : Float, radius : Float ) : Void; + function arc( x : Float, y : Float, radius : Float, startAngle : Float, endAngle : Float, anticlockwise : Bool ) : Void; + function fill() : Void; + function stroke() : Void; + function drawSystemFocusRing( element : Dynamic ) : Void; + function drawCustomFocusRing( element : Dynamic ) : Bool; + function scrollPathIntoView() : Void; + function clip() : Void; + function isPointInPath( x : Float, y : Float ) : Bool; + + // text + var font : String; + var textAlign : String; + var textBaseline : String; + function fillText( text : String, x : Float, y : Float, ?maxWidth : Float ) : Void; + function strokeText( text : String, x : Float, y : Float, ?maxWidth : Float ) : Void; + function measureText( text : String ) : TextMetrics; + + @:overload(function (image:HTMLVideoElement,sx:Float,sy:Float,sw:Float,sh:Float,dx:Float,dy:Float,dw:Float,dh:Float) : Void {} ) + @:overload(function (image:HTMLVideoElement,dx:Float,dy:Float,dw:Float,dh:Float) : Void {} ) + @:overload(function (image:HTMLVideoElement,dx:Float,dy:Float) : Void {} ) + @:overload(function (image:Canvas,sx:Float,sy:Float,sw:Float,sh:Float,dx:Float,dy:Float,dw:Float,dh:Float) : Void {} ) + @:overload(function (image:Canvas,dx:Float,dy:Float,dw:Float,dh:Float) : Void {} ) + @:overload(function (image:Canvas,dx:Float,dy:Float) : Void {} ) + @:overload(function (image:Image,sx:Float,sy:Float,sw:Float,sh:Float,dx:Float,dy:Float,dw:Float,dh:Float) : Void {} ) + @:overload(function (image:Image,dx:Float,dy:Float,dw:Float,dh:Float) : Void {} ) + function drawImage( image : Image, dx : Float, dy : Float ) : Void; + + // pixel manipulation + @:overload(function (imagedata:ImageData) : Void {} ) + function createImageData( sw : Float, sh : Float ) : Void; + function getImageData( sx : Float, sx : Float, sw : Float, sh : Float ) : ImageData; + @:overload(function (imagedata:ImageData,?dirtyX:Float,?dirtyY:Float,?dirtyWidth:Float,?dirtyHeight:Float):Void{}) + function putImageData( imagedata : ImageData, dx : Float, dy : Float ) : Void; + +} diff --git a/lib/html5-haxe/html5/DOMParser.hx b/lib/html5-haxe/html5/DOMParser.hx new file mode 100644 index 0000000..0c1d545 --- /dev/null +++ b/lib/html5-haxe/html5/DOMParser.hx @@ -0,0 +1,9 @@ +package html5; + +extern class DOMParser { + function new() : Void; + //function parseFromBuffer( ) : Dynamic; + //function parseFromStream( ) : Dynamic; + function parseFromString( t : String, mime : String ) : Dynamic; + function getElementsByTagName( name : String ) : Dynamic; +} diff --git a/lib/html5-haxe/html5/DOMTypes.hx b/lib/html5-haxe/html5/DOMTypes.hx new file mode 100644 index 0000000..e21fb80 --- /dev/null +++ b/lib/html5-haxe/html5/DOMTypes.hx @@ -0,0 +1,15 @@ +package html5; + +typedef DOMString = String; +typedef DOMTimeStamp = Int; +typedef DOMUserData = Dynamic; +//typedef DOMObject = Object; +typedef Double = Float; +typedef Long = Int; +typedef Short = Int; +typedef UnsignedLong = Int; +typedef UnsignedShort = Int; +typedef UnsignedByte = Dynamic; +typedef ByteArray = Dynamic; +typedef Byte = Dynamic; + \ No newline at end of file diff --git a/lib/html5-haxe/html5/Database.hx b/lib/html5-haxe/html5/Database.hx new file mode 100644 index 0000000..93ca6e2 --- /dev/null +++ b/lib/html5-haxe/html5/Database.hx @@ -0,0 +1,14 @@ +package html5; + +class Database { + + public function transaction( cb : SQLTransaction->Void ) : Void; + + public static inline function open( name : String, version : String, displayName : String, estimatedSize : Int, + ?creationCallback ) : Database { + return untyped openDatabase( name, version, displayName, estimatedSize, creationCallback ); + } + + //TODO openDatabaseSync + +} diff --git a/lib/html5-haxe/html5/DirectoryEntry.hx b/lib/html5-haxe/html5/DirectoryEntry.hx new file mode 100644 index 0000000..2ff45b0 --- /dev/null +++ b/lib/html5-haxe/html5/DirectoryEntry.hx @@ -0,0 +1,9 @@ +package html5; + +@:native("DirectoryEntry") +extern class DirectoryEntry extends Entry { + function createReader() : DirectoryReader; + function getFile( path : String, ?options : Dynamic, ?successCallback : Dynamic->Void, ?errorCallback : FileError->Void ) : Void; + function getDirectory( path : String, ?options : Dynamic, ?successCallback : Dynamic, ?errorCallback : FileError->Void ) : Void; + function removeRecursively( successCallback : Void->Void, ?errorCallback : FileError->Void ) : Void; +} diff --git a/lib/html5-haxe/html5/DirectoryEntrySync.hx b/lib/html5-haxe/html5/DirectoryEntrySync.hx new file mode 100644 index 0000000..33b352f --- /dev/null +++ b/lib/html5-haxe/html5/DirectoryEntrySync.hx @@ -0,0 +1,9 @@ +package html5; + +@:native("DirectoryEntrySync") +extern class DirectoryEntrySync extends FileEntrySync { + function createReader() : DirectoryReaderSync; + function getFile( path : String, ?options : Dynamic, ?successCallback : Entry->Void, ?errorCallback : FileError->Void ) : FileEntrySync; + function getDirectory( path : String, ?options : Dynamic, ?successCallback : Dynamic, ?errorCallback : FileError->Void ) : DirectoryEntrySync; + function removeRecursively( successCallback : Void->Void, ?errorCallback : FileError->Void ) : Void; +} diff --git a/lib/html5-haxe/html5/DirectoryReader.hx b/lib/html5-haxe/html5/DirectoryReader.hx new file mode 100644 index 0000000..484bbec --- /dev/null +++ b/lib/html5-haxe/html5/DirectoryReader.hx @@ -0,0 +1,6 @@ +package html5; + +@:native("DirectoryReader") +extern class DirectoryReader { + function readEntries( successCallback : Array->Void, ?errorCallback : FileError->Void ) : Void; +} diff --git a/lib/html5-haxe/html5/Entry.hx b/lib/html5-haxe/html5/Entry.hx new file mode 100644 index 0000000..805377d --- /dev/null +++ b/lib/html5-haxe/html5/Entry.hx @@ -0,0 +1,18 @@ +package html5; + +@:native("Entry") +extern class Entry { + + var isFile(default,null) : Bool; + var isDirectory(default,null) : Bool; + var name(default,null) : String; + var fullPath(default,null) : String; + var filesystem(default,null) : FileSystem; + + function getMetadata( successCallback : Dynamic->Void, ?errorCallback : FileError->Void ) : Void; + function moveTo( parent : DirectoryEntry, ?newName : String, ?successCallback : Entry->Void, ?errorCallback : FileError->Void ) : Void; + function copyTo( parent : DirectoryEntry, ?newName : String, ?successCallback : Entry->Void, ?errorCallback : FileError->Void ) : Void; + function toURI( ?mimeType : String ) : Void; + function remove( successCallback : Void->Void, ?errorCallback : FileError->Void ) : Void; + function getParent( successCallbac : Entry->Void, errorCallback : FileError->Void ) : Void; +} diff --git a/lib/html5-haxe/html5/EntrySync.hx b/lib/html5-haxe/html5/EntrySync.hx new file mode 100644 index 0000000..8864d9b --- /dev/null +++ b/lib/html5-haxe/html5/EntrySync.hx @@ -0,0 +1,18 @@ +package html5; + +@:native("EntrySync") +extern class EntrySync { + + var isFile(default,null) : Bool; + var isDirectory(default,null) : Bool; + var name(default,null) : String; + var fullPath(default,null) : String; + var filesystem(default,null) : FileSystem; + + function getMetadata( successCallback : Dynamic->Void, ?errorCallback : FileError->Void ) : Void; + function moveTo( parent : DirectoryEntrySync, ?newName : String, ?successCallback : Entry->Void, ?errorCallback : FileError->Void ) : Void; + function copyTo( parent : DirectoryEntrySync, ?newName : String, ?successCallback : Entry->Void, ?errorCallback : FileError->Void ) : Void; + function toURI( ?mimeType : String ) : Void; + function remove( successCallback : Void->Void, ?errorCallback : FileError->Void ) : Void; + function getParent( successCallbac : Entry->Void, errorCallback : FileError->Void ) : Void; +} diff --git a/lib/html5-haxe/html5/EventSource.hx b/lib/html5-haxe/html5/EventSource.hx new file mode 100644 index 0000000..4c3cad1 --- /dev/null +++ b/lib/html5-haxe/html5/EventSource.hx @@ -0,0 +1,19 @@ +package html5; + +@:native("EventSource") +extern class EventSource { + + static var CONNECTING : Int; + static var OPEN : Int; + static var CLOSED : Int; + + dynamic function onopen() : Void; + dynamic function onmessage(e:Dynamic) : Void; + dynamic function onerror(e:Dynamic) : Void; + + var url(default,null) : String; + var readyState(default,null) : Int; + + function new( url : String ) : Void; + function close() : Void; +} diff --git a/lib/html5-haxe/html5/File.hx b/lib/html5-haxe/html5/File.hx new file mode 100644 index 0000000..1c3169e --- /dev/null +++ b/lib/html5-haxe/html5/File.hx @@ -0,0 +1,7 @@ +package html5; + +@:native("File") +extern class File extends Blob { + var name(default,null) : String; + var lastModifiedDate(default,null) : Date; +} diff --git a/lib/html5-haxe/html5/FileError.hx b/lib/html5-haxe/html5/FileError.hx new file mode 100644 index 0000000..c86bfcb --- /dev/null +++ b/lib/html5-haxe/html5/FileError.hx @@ -0,0 +1,19 @@ +package html5; + +@:native("FileError") +extern class FileError { + static var NOT_FOUND_ERR : Int; //1 + static var SECURITY_ERR : Int; //2 + static var ABORT_ERR : Int; //3 + static var NOT_READABLE_ERR : Int; // 4 + static var ENCODING_ERR : Int; //5 + static var NO_MODIFICATION_ALLOWED_ERR : Int; //6 + static var INVALID_STATE_ERR : Int; //7 + static var SYNTAX_ERR : Int; //8 + static var INVALID_MODIFICATION_ERR : Int; //9 + static var QUOTA_EXCEEDED_ERR : Int; //10 + static var TYPE_MISMATCH_ERR : Int; //11 + static var PATH_EXISTS_ERR : Int; //12 + var code : Int; + function new() : Void; +} diff --git a/lib/html5-haxe/html5/FileList.hx b/lib/html5-haxe/html5/FileList.hx new file mode 100644 index 0000000..fe39960 --- /dev/null +++ b/lib/html5-haxe/html5/FileList.hx @@ -0,0 +1,3 @@ +package html5; + +typedef FileList = Array; diff --git a/lib/html5-haxe/html5/FileReader.hx b/lib/html5-haxe/html5/FileReader.hx new file mode 100644 index 0000000..f906c3b --- /dev/null +++ b/lib/html5-haxe/html5/FileReader.hx @@ -0,0 +1,28 @@ +package html5; + +@:native("FileReader") +extern class FileReader { + + static var EMPTY : Int; + static var LOADING : Int; + static var DONE : Int; + + dynamic function onloadstart( e : Dynamic ) : Void; + dynamic function onprogress( e : Dynamic ) : Void; + dynamic function onabort( e : Dynamic ) : Void; + dynamic function onerror( e : Dynamic ) : Void; + dynamic function onload( e : Dynamic ) : Void; + dynamic function onloadend( e : Dynamic ) : Void; + + var readyState(default,null) : Int; + var result(default,null) : Dynamic; + var error(default,null) : FileError; + + function new() : Void; + + function readAsArrayBuffer( blob : Blob ) : Void; + function readAsBinaryString( blob : Blob ) : Void; + function readAsText( blob : Blob, ?encoding : String ) : Void; + function readAsDataURL( blob : Blob ) : Void; + function abort() : Void; +} diff --git a/lib/html5-haxe/html5/FileSystem.hx b/lib/html5-haxe/html5/FileSystem.hx new file mode 100644 index 0000000..507b974 --- /dev/null +++ b/lib/html5-haxe/html5/FileSystem.hx @@ -0,0 +1,8 @@ +package html5; + +@:native("FileSystem") +extern class FileSystem { + var name(default,null) : String; + var root(default,null) : DirectoryEntry; + +} diff --git a/lib/html5-haxe/html5/FileSystemSync.hx b/lib/html5-haxe/html5/FileSystemSync.hx new file mode 100644 index 0000000..d6f2207 --- /dev/null +++ b/lib/html5-haxe/html5/FileSystemSync.hx @@ -0,0 +1,9 @@ +package html5; + +@:native("FileSystemSync") +extern class FileSystemSync { + var name(default,null) : String; + var root(default,null) : DirectoryEntrySync; + +} + \ No newline at end of file diff --git a/lib/html5-haxe/html5/Geolocation.hx b/lib/html5-haxe/html5/Geolocation.hx new file mode 100644 index 0000000..06571e4 --- /dev/null +++ b/lib/html5-haxe/html5/Geolocation.hx @@ -0,0 +1,37 @@ +package html5; + +typedef Coordinates = { + var latitude : Float; + var longitude : Float; + var altitude : Float; + var accuracy : Float; + var altitudeAccuracy : Float; + var heading : Float; + var speed : Float; +} + +typedef Position = { + var coords : Coordinates; + var timestamp : String; +} + +typedef PositionOptions = { + var enableHighAccuracy : Bool; + var timeout : Float; + var maximumAge : Float; +} + +extern class PositionError { + static var UNKNOWN_ERROR(default,null) : Int; + static var PERMISSION_DENIED(default,null) : Int; + static var POSITION_UNAVAILABLE(default,null) : Int; + static var TIMEOUT(default,null) : Int; + var code(default,null) : Int; + var message(default,null) : String; +} + +@:native("navigator.geolocation") extern class Geolocation { + static function getCurrentPosition( successCallback : Position->Void, ?error : PositionError->Void, ?options : PositionOptions ) : Void; + static function watchPosition( successCallback : Position->Void, ?error : PositionError->Void, ?options : PositionOptions ) : Float; + static function clearWatch( watchId : Int ) : Float; +} diff --git a/lib/html5-haxe/html5/HTMLMediaElement.hx b/lib/html5-haxe/html5/HTMLMediaElement.hx new file mode 100644 index 0000000..bbe2ac7 --- /dev/null +++ b/lib/html5-haxe/html5/HTMLMediaElement.hx @@ -0,0 +1,171 @@ +package html5; +//http://www.w3.org/TR/html5/video.html#htmlmediaelement + +private extern class MediaError { + static var MEDIA_ERR_ABORTED : Int; + static var MEDIA_ERR_NETWORK : Int; + static var MEDIA_ERR_DECODE : Int; + static var MEDIA_ERR_SRC_NOT_SUPPORTED : Int; + var code(default,null) : Int; +} + +private typedef TimeRanges = { + var length(default,null) : Int; + function start( index : Int ) : Float; + function end( index : Int ) : Float; +} + +private typedef MediaController = { + var buffered(default,null) : TimeRanges; + var seekable(default,null) : TimeRanges; + var duration(default,null) : Float; + var currentTime : Float; + var paused(default,null) : Bool; + var played(default,null) : TimeRanges; + + var defaultPlaybackRate : Float; + var playbackRate : Float; + var volume : Float; + var muted : Bool; + + var onemptied : Void->Void; + var onloadedmetadata : Void->Void; + var onloadeddata : Void->Void; + var oncanplay : Void->Void; + var oncanplaytrough : Void->Void; + var onplaying : Void->Void; + var onwaiting : Void->Void; + + var ondurationchange : Void->Void; + var ontimeupdate : Void->Void; + var onplay : Void->Void; + var onpause : Void->Void; + var onratechange : Void->Void; + var onvolumechange : Void->Void; +} + +private typedef TrackList = { + var length(default,null) : Int; + function getID( index : Int ) : String; + function getKind( index : Int ) : String; + function getLabel( index : Int ) : String; + function getLanguage( index : Int ) : String; + var onchange : Void->Void; +} + +private typedef MultipleTrackList = {>TrackList, + function isEnabled( index : Int ) : Bool; + function enable( index : Int ) : Void; + function disable( index : Int ) : Void; +} + +private typedef ExclusiveTrackList = {>TrackList, + var selectedIndex(default,null) : Int; + function select( index : Int ) : Void; +} + +private extern class TextTrack { + + static var NONE(default,null) : Int; + static var LOADING(default,null) : Int; + static var LOADED(default,null) : Int; + static var ERROR(default,null) : Int; + + var kind(default,null) : String; + var label(default,null) : String; + var language(default,null) : String; + + var readyState(default,null) : Int; + var onload : Void->Void; + var onerror : Void->Void; + + static var OFF(default,null) : Int; + static var HIDDEN(default,null) : Int; + static var SHOWING(default,null) : Int; + + var mode : Int; + + var cues(default,null) : TextTrackCueList; + var activeCues(default,null) : TextTrackCueList; + + var oncuechange : Void->Void; +} + +private typedef TextTrackCueList = { + var length(default,null) : Int; + //getter TextTrackCue (in unsigned long index); //TODO ? + function getCueById( id : String ) : TextTrackCue; +} + +private typedef TextTrackCue = { + var track(default,null) : TextTrack; + var id(default,null) : String; + var startTime(default,null) : Float; + var endTime(default,null) : Float; + var pauseOnExit(default,null) : Bool; + function getCueAsSource() : String; +// function getCueAsHTML() : DocumentFragment; //TODO + var onenter : Void->Void; + var onexit : Void->Void; +} + +private typedef MutableTextTrack = {>TextTrack, + function addCue( cue : TextTrackCue ) : Void; + function removeCue( cue : TextTrackCue ) : Void; +} + +extern class HTMLMediaElement { + + static var NETWORK_EMPTY(default,never) : Int; + static var NETWORK_IDLE(default,never) : Int; + static var NETWORK_LOADING(default,never) : Int; + static var NETWORK_NO_SOURCE(default,never) : Int; + + static var HAVE_NOTHING(default,never) : Int; + static var HAVE_METADATA(default,never) : Int; + static var HAVE_CURRENT_DATA(default,never) : Int; + static var HAVE_FUTURE_DATA(default,never) : Int; + static var HAVE_ENOUGH_DATA(default,never) : Int; + + var error(default,null) : MediaError; + var currentSrc(default,null) : String; + var networkState(default,null) : Int; + var preload : String; + var buffered(default,null) : TimeRanges; + + var readyState(default,null) : Int; + var seeking(default,null) : Bool; + + var currentTime : Float; + var initialTime(default,null) : Float; + var duration(default,null) : Float; + var startOffsetTime(default,null) : Float; + var paused(default,null) : Bool; + var defaultPlaybackRate : Float; + var playbackRate : Float; + var played(default,null) : TimeRanges; + var seekable(default,null) : TimeRanges; + var ended(default,null) : Bool; + var autoplay : Bool; + var loop : Bool; + + var mediaGroup : String; + var mediaController : MediaController; + + var controls : Bool; + var volume : Float; + var muted : Bool; + var defaultMuted : Bool; + + var audioTracks(default,null) : MultipleTrackList; + var videoTracks(default,null) : ExclusiveTrackList; + var textTracks : TextTrack; + + function new() : Void; + + function load() : Void; + function canPlayType( type : String ) : String; + function play() : Void; + function pause() : Void; + function addTextTrack( kind : String, ?label : String, ?language : String ) : MutableTextTrack; +} diff --git a/lib/html5-haxe/html5/HTMLVideoElement.hx b/lib/html5-haxe/html5/HTMLVideoElement.hx new file mode 100644 index 0000000..ec88b5f --- /dev/null +++ b/lib/html5-haxe/html5/HTMLVideoElement.hx @@ -0,0 +1,9 @@ +package html5; +//extern class Video +extern class HTMLVideoElement extends HTMLMediaElement { + var width : Int; + var height : Int; + var videoWidth(default,null) : Int; + var videoHeight(default,null) : Int; + var post : String; +} diff --git a/lib/html5-haxe/html5/History.hx b/lib/html5-haxe/html5/History.hx new file mode 100644 index 0000000..e7509cd --- /dev/null +++ b/lib/html5-haxe/html5/History.hx @@ -0,0 +1,11 @@ +package html5; + +@:native("history") extern class History { + static var state(default,null) : Dynamic; + static var length(default,null) : Int; + static function back() : Void; + static function forward() : Void; + static function go( i : Int ) : Void; + static function pushState( stateObject : Dynamic, title : String, url : String ) : Void; + static function replaceState( stateObject : Dynamic, title : String, url : String ) : Void; +} diff --git a/lib/html5-haxe/html5/Html5.hx b/lib/html5-haxe/html5/Html5.hx new file mode 100644 index 0000000..b66563b --- /dev/null +++ b/lib/html5-haxe/html5/Html5.hx @@ -0,0 +1,14 @@ +package html5; +import html5.indexedDB.IDBFactory; + +class Html5 { + + /** + * @link http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html + */ + public static var indexedDb(getIndexedDb, never) : IDBFactory; + + private static function getIndexedDb() : IDBFactory { + return untyped __js__("webkitIndexedDB"); + } +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/Image.hx b/lib/html5-haxe/html5/Image.hx new file mode 100644 index 0000000..89549a5 --- /dev/null +++ b/lib/html5-haxe/html5/Image.hx @@ -0,0 +1,15 @@ +package html5; + +@:native("Image") +extern class Image { + var alt : String; + var src : String; + var useMap : String; + var isMap : Bool; + var width : Int; + var height : Int; + var complete : Bool;//readonly + var onload : Void->Void; + var onerror : Dynamic->Void; + function new() : Void; +} diff --git a/lib/html5-haxe/html5/ImageData.hx b/lib/html5-haxe/html5/ImageData.hx new file mode 100644 index 0000000..3f7767a --- /dev/null +++ b/lib/html5-haxe/html5/ImageData.hx @@ -0,0 +1,10 @@ +package html5; + +typedef ImageData = { + /** The width of the image in pixels; this is a read only unsigned long. */ + var width : Float; + /** The height of the image in pixels; this is a read only unsigned long. */ + var height : Float; + /** A CanvasPixelArray object containing the image data. */ + var data : CanvasPixelArray; +} diff --git a/lib/html5-haxe/html5/JSON.hx b/lib/html5-haxe/html5/JSON.hx new file mode 100644 index 0000000..eebb614 --- /dev/null +++ b/lib/html5-haxe/html5/JSON.hx @@ -0,0 +1,7 @@ +package html5; + +@:native("JSON") +extern class JSON { + static function stringify( v : Dynamic ) : String; + static function parse( v : String ) : Dynamic; +} diff --git a/lib/html5-haxe/html5/LocalFileSystem.hx b/lib/html5-haxe/html5/LocalFileSystem.hx new file mode 100644 index 0000000..baad6a8 --- /dev/null +++ b/lib/html5-haxe/html5/LocalFileSystem.hx @@ -0,0 +1,9 @@ +package html5; + +@:native("LocalFileSystem") +extern class LocalFileSystem { + static var TEMPORARY : Int; + static var PERSISTENT : Int; + static function requestFileSystem( type : Int, size : Float, successCallback : FileSystem->Void, ?errorCallback : FileError->Void ) : Void; + static function resolveLocalFileSystemURI( uri : String, successCallback : FileSystem->Void, ?errorCallback : FileError->Void ) : Void; +} diff --git a/lib/html5-haxe/html5/LocalFileSystemSync.hx b/lib/html5-haxe/html5/LocalFileSystemSync.hx new file mode 100644 index 0000000..b2e8990 --- /dev/null +++ b/lib/html5-haxe/html5/LocalFileSystemSync.hx @@ -0,0 +1,9 @@ +package html5; + +@:native("LocalFileSystemSync") +extern LocalFileSystemSync { + static var TEMPORARY : Int; + static var PERSISTENT : Int; + static function requestFileSystemSync( type : Int, size : Float ) : FileSystemSync; + static function resolveLocalFileSystemSyncURI( uri : String ) : EntrySync; +} diff --git a/lib/html5-haxe/html5/MediaTimeRanges.hx b/lib/html5-haxe/html5/MediaTimeRanges.hx new file mode 100644 index 0000000..4ccb50d --- /dev/null +++ b/lib/html5-haxe/html5/MediaTimeRanges.hx @@ -0,0 +1,7 @@ +package html5; + +typedef MediaTimeRanges = { + var length:Float; + var start:Float; // ?? + var end:Float; // ?? +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/Notification.hx b/lib/html5-haxe/html5/Notification.hx new file mode 100644 index 0000000..4e4362f --- /dev/null +++ b/lib/html5-haxe/html5/Notification.hx @@ -0,0 +1,10 @@ +package html5; + +@:native("Notification") +extern class Notification { + function show() : Void; + function cancel() : Void; + var ondisplay : Void->Void; + var onerror : Void->Void; + var onclose : Void->Void; +} diff --git a/lib/html5-haxe/html5/NotificationCenter.hx b/lib/html5-haxe/html5/NotificationCenter.hx new file mode 100644 index 0000000..b8ffb60 --- /dev/null +++ b/lib/html5-haxe/html5/NotificationCenter.hx @@ -0,0 +1,8 @@ +package html5; + +@:native("window.webkitNotifications") extern class NotificationCenter { + static function createNotification( iconUrl : String, title : String, body : String ) : Notification; + static function createHTMLNotification( url : String ) : Notification; + static function requestPermission( ?cb : Void->Void ) : Void; + static function checkPermission() : Int; +} diff --git a/lib/html5-haxe/html5/SQLError.hx b/lib/html5-haxe/html5/SQLError.hx new file mode 100644 index 0000000..0a1b133 --- /dev/null +++ b/lib/html5-haxe/html5/SQLError.hx @@ -0,0 +1,16 @@ +package html5; + +typedef SQLError = { + + var UNKNOWN_ERR : Int; + var DATABASE_ERR : Int; + var VERSION_ERR : Int; + var TOO_LARGE_ERR : Int; + var QUOTA_ERR : Int; + var SYNTAX_ERR : Int; + var CONSTRAINT_ERR : Int; + var TIMEOUT_ERR : Int; + + var code(default,null) : Int; + var message(default,null) : String; +} diff --git a/lib/html5-haxe/html5/SQLResultSet.hx b/lib/html5-haxe/html5/SQLResultSet.hx new file mode 100644 index 0000000..3c57429 --- /dev/null +++ b/lib/html5-haxe/html5/SQLResultSet.hx @@ -0,0 +1,7 @@ +package html5; + +typedef SQLResultSet = { + var insertId(default,null) : Int; + var rowsAffected(default,null) : Int; + var rows(default,null) : SQLResultSetRowList; +} diff --git a/lib/html5-haxe/html5/SQLResultSetRowList.hx b/lib/html5-haxe/html5/SQLResultSetRowList.hx new file mode 100644 index 0000000..5087595 --- /dev/null +++ b/lib/html5-haxe/html5/SQLResultSetRowList.hx @@ -0,0 +1,6 @@ +package html5; + +typedef SQLResultSetRowList = { + var length(default,null) : Int; + function item( index : Int ) : Dynamic; +} diff --git a/lib/html5-haxe/html5/SQLTransaction.hx b/lib/html5-haxe/html5/SQLTransaction.hx new file mode 100644 index 0000000..e3b8011 --- /dev/null +++ b/lib/html5-haxe/html5/SQLTransaction.hx @@ -0,0 +1,8 @@ +package html5; + +typedef SQLTransaction = { + function executeSql( sqlStatement : String, + ?arguments : Array, + ?cb : SQLTransaction->SQLResultSet->Void, + ?errorCb : SQLTransaction->SQLError->Void ) : Void; +} diff --git a/lib/html5-haxe/html5/SharedWorker.hx b/lib/html5-haxe/html5/SharedWorker.hx new file mode 100644 index 0000000..6b12d48 --- /dev/null +++ b/lib/html5-haxe/html5/SharedWorker.hx @@ -0,0 +1,6 @@ +package html5; + +extern class SharedWorker { + var port(default,null) : Dynamic; // MessagePort; + function new( scriptURL : String, ?name : String ) : Void; +} diff --git a/lib/html5-haxe/html5/Storage.hx b/lib/html5-haxe/html5/Storage.hx new file mode 100644 index 0000000..3fa6e7a --- /dev/null +++ b/lib/html5-haxe/html5/Storage.hx @@ -0,0 +1,3 @@ +package html5; + +typedef Storage = LocalStorage; diff --git a/lib/html5-haxe/html5/TextMetrics.hx b/lib/html5-haxe/html5/TextMetrics.hx new file mode 100644 index 0000000..5110631 --- /dev/null +++ b/lib/html5-haxe/html5/TextMetrics.hx @@ -0,0 +1,5 @@ +package html5; + +typedef TextMetrics = { + var width : Float; +}; diff --git a/lib/html5-haxe/html5/WebSocket.hx b/lib/html5-haxe/html5/WebSocket.hx new file mode 100644 index 0000000..7cd0bac --- /dev/null +++ b/lib/html5-haxe/html5/WebSocket.hx @@ -0,0 +1,30 @@ +package html5; + +extern class WebSocket { + + static var CONNECTING : Int; + static var OPEN : Int; + static var CLOSING : Int; + static var CLOSED : Int; + + var readyState(default,null) : Int; + var bufferedAmount(default,null) : Int; + + dynamic function onopen() : Void; + dynamic function onmessage(e:{data:String}) : Void; //correct? + dynamic function onclose() : Void; + dynamic function onerror() : Void; + + var url(default,null) : String; + var extensions(default,null) : String; + var protocol(default,null) : String; + var binaryType : String; + + function new( url : String, ?protocol : Dynamic ) : Void; + + @:overload(function( data : Blob ):Void{}) + @:overload(function( data : ArrayBuffer ):Void{}) + function send( data : String ) : Bool; + + function close( ?code : Int, ?reason : String ) : Void; +} diff --git a/lib/html5-haxe/html5/Worker.hx b/lib/html5-haxe/html5/Worker.hx new file mode 100644 index 0000000..62b65f1 --- /dev/null +++ b/lib/html5-haxe/html5/Worker.hx @@ -0,0 +1,9 @@ +package html5; + +@:native("Worker") +extern class Worker { + var onmessage : Dynamic->Void; + function new( scriptURL : String ) : Void; + function terminate() : Void; + function postMessage( message : Dynamic, ?ports : Array ) : Void; +} diff --git a/lib/html5-haxe/html5/WorkerUtils.hx b/lib/html5-haxe/html5/WorkerUtils.hx new file mode 100644 index 0000000..4ebdd80 --- /dev/null +++ b/lib/html5-haxe/html5/WorkerUtils.hx @@ -0,0 +1,6 @@ +package html5; + +extern class WorkerUtils { + static var navigator(default,null) : Dynamic; //WorkerNavigator; + static function importScripts( urls : String ) : Void; +} diff --git a/lib/html5-haxe/html5/XMLHttpRequest.hx b/lib/html5-haxe/html5/XMLHttpRequest.hx new file mode 100644 index 0000000..7244a92 --- /dev/null +++ b/lib/html5-haxe/html5/XMLHttpRequest.hx @@ -0,0 +1,51 @@ +package html5; + +import js.Dom; + +enum XMLHttpRequestResponseType { + arraybuffer; + blob; + document; + json; + text; +} + +extern class XMLHttpRequest { + + // states + static var UNSENT(default,never) : Int; + static var OPENED(default,never) : Int; + static var HEADERS_RECEIVED(default,never) : Int; + static var LOADING(default,never) : Int; + static var DONE(default,never) : Int; + var readyState(default,null) : Int; + + // event handler + var onreadystatechange : Void -> Void; + + function new() : Void; + + // request + function open( method : String, url : String, ?async : Bool, ?user : String, ?password : String ) : Void; + function setRequestHeader( name : String, value : String ) : Void; + var upload(default,null) : Dynamic; //XMLHttpRequestUpload; + var withCredentials(default,null) : Dynamic; + @:overload( function( data : FormData ) : Void {} ) + @:overload( function( data : String ) : Void {} ) + @:overload( function( data : Document ) : Void {} ) + @:overload( function( data : Blob ) : Void {} ) + @:overload( function( data : ArrayBuffer ) : Void {} ) + function send() : Void; + function abort() : Void; + + // response + var status(default,null) : Int; + var statusText(default,null) : String; + function getResponseHeader( name : String ) : String; + function getAllResponseHeaders() : String; + function overrideMimeType( mime : String ) : Void; + var responseType(default,null) : XMLHttpRequestResponseType; + var response(default,null) : Dynamic; + var responseText(default,null) : String; + var responseXML(default,null) : Document; +} diff --git a/lib/html5-haxe/html5/XMLSerializer.hx b/lib/html5-haxe/html5/XMLSerializer.hx new file mode 100644 index 0000000..cbb96e5 --- /dev/null +++ b/lib/html5-haxe/html5/XMLSerializer.hx @@ -0,0 +1,7 @@ +package html5; + +extern class XMLSerializer { + function new() : Void; + function serializeToString( d : Dynamic ) : String; + function serializeToStream( d : Dynamic, stream : Dynamic, encoding : String ) : Void; +} diff --git a/lib/html5-haxe/html5/indexedDB/IDBDatabase.hx b/lib/html5-haxe/html5/indexedDB/IDBDatabase.hx new file mode 100644 index 0000000..fd9f0b7 --- /dev/null +++ b/lib/html5-haxe/html5/indexedDB/IDBDatabase.hx @@ -0,0 +1,21 @@ +package html5.indexedDB; + +/** + * @link http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBDatabase + */ + +typedef IDBDatabase = { + var name(default, never) : String; + var version(default, never) : String; + var objectStoreNames(default, never) : Array; + + function createObjectStore( name : String, ?keyPath : String, ?autoIncrement : Bool ) : IDBObjectStore; + function deleteObjectStore( name : String ) : Void; + function setVersion( version : String ) : IDBVersionChangeRequest; + function transaction( storeNames : Array, ?mode : Int ) : IDBTransaction; + function close() : Void; + + var onabort : Void -> Void; + var onerror : Void -> Void; + var onversionchange : Void -> Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/indexedDB/IDBFactory.hx b/lib/html5-haxe/html5/indexedDB/IDBFactory.hx new file mode 100644 index 0000000..d159dae --- /dev/null +++ b/lib/html5-haxe/html5/indexedDB/IDBFactory.hx @@ -0,0 +1,9 @@ +package html5.indexedDB; + +/** + * @link http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html + */ + +typedef IDBFactory = { + function open( name : String ) : IDBRequest; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/indexedDB/IDBObjectStore.hx b/lib/html5-haxe/html5/indexedDB/IDBObjectStore.hx new file mode 100644 index 0000000..205d3b5 --- /dev/null +++ b/lib/html5-haxe/html5/indexedDB/IDBObjectStore.hx @@ -0,0 +1,13 @@ +package html5.indexedDB; + +typedef IDBObjectStore = { + var name(default, never) : String; + var keyPath(default, never) : String; + var indexNames(default, never) : Array; + + function put( value : Dynamic, key : Dynamic ) : IDBRequest; + function add( value : Dynamic, key : Dynamic ) : IDBRequest; + function delete( key : Dynamic ) : IDBRequest; + function get( key : Dynamic ) : IDBRequest; + function clear() : IDBRequest; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/indexedDB/IDBRequest.hx b/lib/html5-haxe/html5/indexedDB/IDBRequest.hx new file mode 100644 index 0000000..b30bfcb --- /dev/null +++ b/lib/html5-haxe/html5/indexedDB/IDBRequest.hx @@ -0,0 +1,17 @@ +package html5.indexedDB; +import js.Dom; + +@:native("webkitIDBRequest") +extern class IDBRequest { + static var LOADING(default, never) : Int; + static var DONE(default, never) : Int; + + var result(default, never) : Dynamic; + var errorCode(default, never) : Int; + var source(default, never) : Dynamic; + + var readyState(default, never) : Int; + + var onsuccess : Event -> Void; + var onerror : Event -> Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/indexedDB/IDBTransaction.hx b/lib/html5-haxe/html5/indexedDB/IDBTransaction.hx new file mode 100644 index 0000000..545b5bb --- /dev/null +++ b/lib/html5-haxe/html5/indexedDB/IDBTransaction.hx @@ -0,0 +1,16 @@ +package html5.indexedDB; +import js.Dom; + +@:native("webkitIDBTransaction") +extern class IDBTransaction { + static var READ_ONLY(default, never) : Int; + static var READ_WRITE(default, never) : Int; + static var VERSION_CHANGE(default, never) : Int; + var mode(default, never) : Int; + var db(default, never) : IDBDatabase; + function objectStore( name : String ) : IDBObjectStore; + function abort() : Void; + var onabort : Event -> Void; + var oncomplete : Event -> Void; + var onerror : Event -> Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/indexedDB/IDBVersionChangeRequest.hx b/lib/html5-haxe/html5/indexedDB/IDBVersionChangeRequest.hx new file mode 100644 index 0000000..73f88fa --- /dev/null +++ b/lib/html5-haxe/html5/indexedDB/IDBVersionChangeRequest.hx @@ -0,0 +1,6 @@ +package html5.indexedDB; +import js.Dom; + +typedef IDBVersionChangeRequest = { > IDBRequest, + var onblocked : Event -> Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/typedArrays/ArrayBuffer.hx b/lib/html5-haxe/html5/typedArrays/ArrayBuffer.hx new file mode 100644 index 0000000..3e08455 --- /dev/null +++ b/lib/html5-haxe/html5/typedArrays/ArrayBuffer.hx @@ -0,0 +1,7 @@ +package html5.typedArrays; + +@:native("ArrayBuffer") +extern class ArrayBuffer { + function new( length : Int ) : Void; + var byteLength(default, never) : Int; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/typedArrays/Int8Array.hx b/lib/html5-haxe/html5/typedArrays/Int8Array.hx new file mode 100644 index 0000000..9a4b129 --- /dev/null +++ b/lib/html5-haxe/html5/typedArrays/Int8Array.hx @@ -0,0 +1,6 @@ +package html5.typedArrays; + +@:native("Int8Array") +extern class Int8Array { + public function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/typedArrays/TypedArraysHelp.hx b/lib/html5-haxe/html5/typedArrays/TypedArraysHelp.hx new file mode 100644 index 0000000..fe9f94c --- /dev/null +++ b/lib/html5-haxe/html5/typedArrays/TypedArraysHelp.hx @@ -0,0 +1,10 @@ +package html5.typedArrays; +import haxe.io.BytesData; + +class TypedArraysHelp { + + public static function ArrayBufferToBytesData( arrayBuffer : ArrayBuffer) : BytesData { + return cast new Uint8Array(arrayBuffer); + } + +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/typedArrays/Uint8Array.hx b/lib/html5-haxe/html5/typedArrays/Uint8Array.hx new file mode 100644 index 0000000..5d36119 --- /dev/null +++ b/lib/html5-haxe/html5/typedArrays/Uint8Array.hx @@ -0,0 +1,6 @@ +package html5.typedArrays; + +@:native("Uint8Array") +extern class Uint8Array { + public function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/webStorage/LocalStorage.hx b/lib/html5-haxe/html5/webStorage/LocalStorage.hx new file mode 100644 index 0000000..90e324b --- /dev/null +++ b/lib/html5-haxe/html5/webStorage/LocalStorage.hx @@ -0,0 +1,10 @@ +package html5.webStorage; + +@:native("localStorage") extern class LocalStorage { + static var length(default,null) : Int; + static function key( index : Int ) : String; + static function setItem( key : String, value : Dynamic ) : Void; + static function getItem( key : String ) : Dynamic; + static function removeItem( key : String ) : Void; + static function clear() : Void; +} diff --git a/lib/html5-haxe/html5/xhr/XMLHttpRequest2.hx b/lib/html5-haxe/html5/xhr/XMLHttpRequest2.hx new file mode 100644 index 0000000..8f31a37 --- /dev/null +++ b/lib/html5-haxe/html5/xhr/XMLHttpRequest2.hx @@ -0,0 +1,17 @@ +package html5.xhr; +import js.XMLHttpRequest; + +/** + * XMLHttpRequest Level 2 + * + * @link http://www.w3.org/TR/XMLHttpRequest2/ + */ + +@:native("XMLHttpRequest") +extern class XMLHttpRequest2 extends XMLHttpRequest { + + public function overrideMimeType(mime:String):Void; + public var responseType(default, default):String; + public var response(default, default):Dynamic; + +} \ No newline at end of file diff --git a/lib/html5-haxe/html5/xhr/XMLHttpRequest2Help.hx b/lib/html5-haxe/html5/xhr/XMLHttpRequest2Help.hx new file mode 100644 index 0000000..2db298e --- /dev/null +++ b/lib/html5-haxe/html5/xhr/XMLHttpRequest2Help.hx @@ -0,0 +1,161 @@ +package html5.xhr; + +enum RequestMethod { + + /** + * Asks for the response identical to the one that would correspond to a + * GET request, but without the response body. This is useful for + * retrieving meta-information written in response headers, without having + * to transport the entire content. + */ + HEAD; + + /** + * Requests a representation of the specified resource. Requests using GET + * (and a few other HTTP methods) "SHOULD NOT have the significance of + * taking an action other than retrieval". The W3C has published guidance + * principles on this distinction, saying, "Web application design should + * be informed by the above principles, but also by the relevant limitations." + */ + GET; + + /** + * Submits data to be processed (e.g., from an HTML form) to the identified + * resource. The data is included in the body of the request. This may + * result in the creation of a new resource or the updates of existing + * resources or both. + */ + POST; + + /** + * Uploads a representation of the specified resource. + */ + PUT; + + /** + * Deletes the specified resource. + */ + DELETE; + + /** + * Echoes back the received request, so that a client can see what (if any) + * changes or additions have been made by intermediate servers. + */ + TRACE; + + /** + * Returns the HTTP methods that the server supports for specified URL. + * This can be used to check the functionality of a web server by + * requesting '*' instead of a specific resource. + */ + OPTIONS; + + /** + * Converts the request connection to a transparent TCP/IP tunnel, usually + * to facilitate SSL-encrypted communication (HTTPS) through an unencrypted + * HTTP proxy. + */ + CONNECT; + + /** + * Is used to apply partial modifications to a resource. + */ + PATCH; +} + +enum ReadyState { + + /** + * When constructed, the XMLHttpRequest object must be in the UNSENT state. + */ + UNSENT; + + /** + * The OPENED state is the state of the object when the open() method has been + * successfully invoked. During this state request headers can be set using + * setRequestHeader() and the request can be made using send(). + */ + OPENED; + + /** + * The HEADERS_RECEIVED state is the state of the object when all response + * headers have been received. + */ + HEADERS_RECEIVED; + /** + * The LOADING state is the state of the object when the response entity body + * is being received. + */ + LOADING; + + /** + * The DONE state is the state of the object when either the data transfer has + * been completed or something went wrong during the transfer (infinite + * redirects for instance). + */ + DONE; +} + +enum HttpStatusCode { + + /** + * Standard response for successful HTTP requests. The actual response will + * depend on the request method used. In a GET request, the response will + * contain an entity corresponding to the requested resource. In a POST + * request the response will contain an entity describing or containing + * the result of the action. + */ + OK; + + /** + * The requested resource could not be found but may be available again in the future. + * Subsequent requests by the client are permissible. + */ + NOT_FOUND; + + /** + * A generic error message, given when no more specific message is suitable. + */ + INTERNAL_SERVER_ERROR; +} + +class XMLHttpRequest2Help { + + public static function requestMethodValue(requestMethod:RequestMethod):String { + return switch (requestMethod) { + case HEAD: "HEAD"; + case GET: "GET"; + case POST: "POST"; + case PUT: "PUT"; + case DELETE: "DELETE"; + case TRACE: "TRACE"; + case OPTIONS: "OPTIONS"; + case CONNECT: "CONNECT"; + case PATCH: "PATCH"; + } + } + + public static function readyStateValue(readyState:ReadyState):Int { + return switch (readyState) { + case UNSENT: 0; + case OPENED : 1; + case HEADERS_RECEIVED: 2; + case LOADING : 3; + case DONE : 4; + } + } + + public static function httpStatusCodeValue(httpStatusCode:HttpStatusCode):Int { + return switch(httpStatusCode) { + case OK: 200; + case NOT_FOUND: 404; + case INTERNAL_SERVER_ERROR: 500; + } + } + + public static function setBinaryModeForChrome(xhr:XMLHttpRequest2):Void { + xhr.overrideMimeType("text/plain; charset=x-user-defined"); + xhr.responseType = "arraybuffer"; + } + +} \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/.gitignore b/lib/html5-haxe/html5Test/.gitignore new file mode 100644 index 0000000..532c2f7 --- /dev/null +++ b/lib/html5-haxe/html5Test/.gitignore @@ -0,0 +1 @@ +bin/html5-haxe-test.js \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/Main.hx b/lib/html5-haxe/html5Test/Main.hx new file mode 100644 index 0000000..88dff56 --- /dev/null +++ b/lib/html5-haxe/html5Test/Main.hx @@ -0,0 +1,19 @@ +package html5Test; +import haxe.Firebug; +import html5Test.specs.IndexedDBSpec; +import jasmine.Jasmine; + +class Main { + static function main() { + new Main(); + } + + public function new() { + Firebug.redirectTraces(); + + new IndexedDBSpec(); + + Jasmine.getEnv().addReporter(Jasmine.newTrivialReporter()); + Jasmine.getEnv().execute(); + } +} \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/bin/SpecRunner.html b/lib/html5-haxe/html5Test/bin/SpecRunner.html new file mode 100644 index 0000000..ea9e716 --- /dev/null +++ b/lib/html5-haxe/html5Test/bin/SpecRunner.html @@ -0,0 +1,17 @@ + + + + html5-haxe test runner + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/MIT.LICENSE b/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/MIT.LICENSE new file mode 100644 index 0000000..1eb9b49 --- /dev/null +++ b/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/MIT.LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008-2010 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine-html.js b/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine-html.js new file mode 100644 index 0000000..81402b9 --- /dev/null +++ b/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine-html.js @@ -0,0 +1,188 @@ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + var results = suite.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.totalCount == 0) { // todo: change this to check results.skipped + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap["spec"]) return true; + return spec.getFullName().indexOf(paramMap["spec"]) == 0; +}; diff --git a/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine.css b/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine.css new file mode 100644 index 0000000..6583fe7 --- /dev/null +++ b/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine.css @@ -0,0 +1,166 @@ +body { + font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; +} + + +.jasmine_reporter a:visited, .jasmine_reporter a { + color: #303; +} + +.jasmine_reporter a:hover, .jasmine_reporter a:active { + color: blue; +} + +.run_spec { + float:right; + padding-right: 5px; + font-size: .8em; + text-decoration: none; +} + +.jasmine_reporter { + margin: 0 5px; +} + +.banner { + color: #303; + background-color: #fef; + padding: 5px; +} + +.logo { + float: left; + font-size: 1.1em; + padding-left: 5px; +} + +.logo .version { + font-size: .6em; + padding-left: 1em; +} + +.runner.running { + background-color: yellow; +} + + +.options { + text-align: right; + font-size: .8em; +} + + + + +.suite { + border: 1px outset gray; + margin: 5px 0; + padding-left: 1em; +} + +.suite .suite { + margin: 5px; +} + +.suite.passed { + background-color: #dfd; +} + +.suite.failed { + background-color: #fdd; +} + +.spec { + margin: 5px; + padding-left: 1em; + clear: both; +} + +.spec.failed, .spec.passed, .spec.skipped { + padding-bottom: 5px; + border: 1px solid gray; +} + +.spec.failed { + background-color: #fbb; + border-color: red; +} + +.spec.passed { + background-color: #bfb; + border-color: green; +} + +.spec.skipped { + background-color: #bbb; +} + +.messages { + border-left: 1px dashed gray; + padding-left: 1em; + padding-right: 1em; +} + +.passed { + background-color: #cfc; + display: none; +} + +.failed { + background-color: #fbb; +} + +.skipped { + color: #777; + background-color: #eee; + display: none; +} + + +/*.resultMessage {*/ + /*white-space: pre;*/ +/*}*/ + +.resultMessage span.result { + display: block; + line-height: 2em; + color: black; +} + +.resultMessage .mismatch { + color: black; +} + +.stackTrace { + white-space: pre; + font-size: .8em; + margin-left: 10px; + max-height: 5em; + overflow: auto; + border: 1px inset red; + padding: 1em; + background: #eef; +} + +.finished-at { + padding-left: 1em; + font-size: .6em; +} + +.show-passed .passed, +.show-skipped .skipped { + display: block; +} + + +#jasmine_content { + position:fixed; + right: 100%; +} + +.runner { + border: 1px solid gray; + display: block; + margin: 5px 0; + padding: 2px 0 2px 10px; +} diff --git a/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine.js b/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine.js new file mode 100644 index 0000000..63e415d --- /dev/null +++ b/lib/html5-haxe/html5Test/bin/jasmine-1.0.2/jasmine.js @@ -0,0 +1,2421 @@ +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; + +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +jasmine.DEFAULT_UPDATE_INTERVAL = 250; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +jasmine.getGlobal = function() { + function getGlobal() { + return this; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for(var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + + this.message = this.passed_ ? 'Passed.' : params.message; + this.trace = this.passed_ ? '' : new Error(this.message); +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj['nodeType'] > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + if (!jasmine.isArray_(methodNames) || methodNames.length == 0) { + throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @returns a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); +}; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + try { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + } catch(e) { + } + try { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + } catch(e) { + } + try { + return new ActiveXObject("Msxml2.XMLHTTP"); + } catch(e) { + } + try { + return new ActiveXObject("Microsoft.XMLHTTP"); + } catch(e) { + } + throw new Error("This browser does not support XMLHttpRequest."); +} : XMLHttpRequest; +/** + * @namespace + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass; +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (jasmine.version_) { + var version = this.version(); + return version.major + "." + version.minor + "." + version.build + " revision " + version.revision; + } else { + return "version unknown"; + } +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + this.currentSuite = parentSuite; + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj != null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length == 0 && mismatchValues.length == 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a instanceof jasmine.Matchers.Any) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.Any) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + return (a == b); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toNotEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +jasmine.Matchers.prototype.toBeNull = function() { + return (this.actual === null); +}; + +/** + * Matcher that boolean not-nots the actual. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + this.message = function() { + if (this.actual.callCount == 0) { + // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] + return [ + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was." + ]; + } else { + return [ + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) + ]; + } + }; + + return this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" + ] + }; + + return !this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toNotContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected exception was thrown by the actual. + * + * @param {String} expected + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + this.message = function() { + if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { + return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.matches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.toString = function() { + return ''; +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + if (this.ppNestLevel_ > 40) { + throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); + } + + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value instanceof jasmine.Matchers.Any) { + this.emitScalar(value.toString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + value + "'"); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block) { + this.blocks.unshift(block); +}; + +jasmine.Queue.prototype.add = function(block) { + this.blocks.push(block); +}; + +jasmine.Queue.prototype.insertNext = function(block) { + this.blocks.splice((this.index + this.offset + 1), 0, block); + this.offset++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !this.abort) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception' + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this)); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); + } + for (i = 0; i < this.afterCallbacks.length; i++) { + this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); + } + for (suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + + +jasmine.version_= { + "major": 1, + "minor": 0, + "build": 2, + "revision": 1298837858 +}; diff --git a/lib/html5-haxe/html5Test/build.hxml b/lib/html5-haxe/html5Test/build.hxml new file mode 100644 index 0000000..4b88d2f --- /dev/null +++ b/lib/html5-haxe/html5Test/build.hxml @@ -0,0 +1,4 @@ +-cp ../ +-cp jasmine-haxe-1.0.2 +-js bin/html5-haxe-test.js +-main html5Test.Main \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Env.hx b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Env.hx new file mode 100644 index 0000000..4cf0e68 --- /dev/null +++ b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Env.hx @@ -0,0 +1,6 @@ +package jasmine; + +typedef Env = { + function addReporter( reporter : Reporter ) : Void; + function execute() : Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/J.hx b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/J.hx new file mode 100644 index 0000000..e83608b --- /dev/null +++ b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/J.hx @@ -0,0 +1,49 @@ +package jasmine; + +class J { + + public static function beforeEach( beforeEachFunction : Void -> Void ) : Void { + untyped __js__("beforeEach(beforeEachFunction)"); + } + + public static function afterEach( afterEachFunction : Void -> Void ) : Void { + untyped __js__("afterEach(afterEachFunction)"); + } + + public static function describe( description : String, specDefinitions : Void -> Void ) : Void { + untyped __js__("describe(description, specDefinitions)"); + } + + public static function xdescribe( description : String, specDefinitions : Void -> Void ) : Void { + untyped __js__("xdescribe(description, specDefinitions)"); + } + + public static function it( description : String, func : Void -> Void ) : Void { + untyped __js__("it(description, func)"); + } + + public static function xit( description : String, func : Void -> Void ) : Void { + untyped __js__("xit(description, func)"); + } + + public static function expect( actual : Dynamic ) : Matchers { + return untyped __js__("expect(actual)"); + } + + public static function runs( func : Void -> Void ) : Void { + untyped __js__("runs(func)"); + } + + public static function waits( timeoutMilliseconds : Int ) : Void { + untyped __js__("waits(timeoutMilliseconds)"); + } + + public static function waitsFor( func : Void -> Bool, ?message : String, ?timeoutMilliseconds : Int ) : Void { + untyped __js__("waitsFor(func, message, timeoutMilliseconds)"); + } + + public static function spyOn( x : Dynamic, method : String ) : Spy { + return untyped __js__("spyOn(x, method)"); + } + +} \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Jasmine.hx b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Jasmine.hx new file mode 100644 index 0000000..300ef92 --- /dev/null +++ b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Jasmine.hx @@ -0,0 +1,20 @@ +package jasmine; +import js.Lib; + +/** + * @link http://pivotal.github.com/jasmine/jsdoc/index.html + */ + +class Jasmine { + public static function getEnv() : Env untyped { + return jasmine.getEnv(); + } + + public static function newTrivialReporter() : Reporter { + return untyped __js__("new jasmine.TrivialReporter()"); + } + + public static function createSpy( name : String ) : Spy untyped { + return jasmine.createSpy(name); + } +} \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Matchers.hx b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Matchers.hx new file mode 100644 index 0000000..401f6c5 --- /dev/null +++ b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Matchers.hx @@ -0,0 +1,20 @@ +package jasmine; + +typedef Matchers = { + var not(default, never) : Matchers; + + function toBe( expected : Dynamic ) : Void; + function toBeDefined() : Void; + function toBeFalsy() : Void; + function toBeGreaterThan( expected : Dynamic ) : Void; + function toBeLessThan( expected : Dynamic ) : Void; + function toBeNull() : Void; + function toBeTruthy() : Void; + function toBeUndefined() : Void; + function toContain( expected : Dynamic ) : Void; + function toEqual( expected : Dynamic ) : Void; + function toHaveBeenCalled() : Void; + function toHaveBeenCalledWith( arguments : Dynamic ) : Void; + function toMatch( expected : Dynamic ) : Void; + function toThrow( expected : String ) : Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Reporter.hx b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Reporter.hx new file mode 100644 index 0000000..b4282cc --- /dev/null +++ b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Reporter.hx @@ -0,0 +1,5 @@ +package jasmine; + +typedef Reporter = { + function log( str : String ) : Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Spy.hx b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Spy.hx new file mode 100644 index 0000000..89e1e48 --- /dev/null +++ b/lib/html5-haxe/html5Test/jasmine-haxe-1.0.2/jasmine/Spy.hx @@ -0,0 +1,12 @@ +package jasmine; + +typedef Spy = { + var callCount(default, never) : Int; + + function andCallFake( fakeFunc : Dynamic ) : Spy; + function andCallThrough() : Spy; + function andReturn( value : Dynamic ) : Spy; + function andThrow( exceptionMsg : String ) : Spy; + function plan() : Void; + function reset() : Void; +} \ No newline at end of file diff --git a/lib/html5-haxe/html5Test/specs/IndexedDBSpec.hx b/lib/html5-haxe/html5Test/specs/IndexedDBSpec.hx new file mode 100644 index 0000000..989be2d --- /dev/null +++ b/lib/html5-haxe/html5Test/specs/IndexedDBSpec.hx @@ -0,0 +1,156 @@ +package html5Test.specs; +import html5.Html5; +import html5.indexedDB.IDBDatabase; +import html5.indexedDB.IDBRequest; +import html5.indexedDB.IDBTransaction; +import jasmine.J; +import jasmine.Jasmine; +import js.Dom; + +class IndexedDBSpec { + + private inline static var DATABASE_NAME = "TestDatabase"; + private inline static var DATABASE_VERSION = "1"; + private inline static var OBJECT_STORE_NAME = "torrent"; + + public function new() { + var me = this; + + J.describe("IndexedDB", function() { + + var db : IDBDatabase = null; + + J.it("should open", function() { + var request = Html5.indexedDb.open(DATABASE_NAME); + request.onsuccess = function( e : Event ) { + db = request.result; + }; + J.expect(db).toBeNull(); + + J.waitsFor(function() { + return request.readyState == IDBRequest.DONE; + }, "open database request to finish"); + + J.runs(function() { + J.expect(db).not.toBeNull(); + J.expect(db.name).toBe(DATABASE_NAME); + }); + }); + + J.it("should set version", function() { + var r = db.setVersion(DATABASE_VERSION); + r.onsuccess = cast Jasmine.createSpy("007"); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; } ); + J.runs(function() { + J.expect(r.onsuccess).toHaveBeenCalled(); + J.expect(db.version).toBe(DATABASE_VERSION); + }); + }); + + J.it("should create an object store", function() { + var r = db.setVersion(DATABASE_VERSION); + r.onsuccess = function( e : Event ) { + var os = db.createObjectStore(OBJECT_STORE_NAME); + J.expect(os).not.toBeNull(); + J.expect(os.name).toBe(OBJECT_STORE_NAME); + } + var spy = J.spyOn(r, "onsuccess").andCallThrough(); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; } ); + J.runs(function() { J.expect(spy).toHaveBeenCalled(); } ); + } ); + + J.it("should add a key value pair to an object store", function() { + var t = db.transaction([OBJECT_STORE_NAME], IDBTransaction.READ_WRITE); + var completeSpy = J.spyOn(t, "oncomplete"); + J.expect(t.mode).toBe(IDBTransaction.READ_WRITE); + J.expect(t.db).not.toBeNull(); + var os = t.objectStore(OBJECT_STORE_NAME); + J.expect(os).not.toBeNull(); + J.expect(os.name).toBe(OBJECT_STORE_NAME); + var r = os.add("value", "key"); + r.onsuccess = cast Jasmine.createSpy("007"); + J.waitsFor(function() { return completeSpy.callCount == 1; }, "transaction"); + J.runs(function() { + J.expect(t.oncomplete).toHaveBeenCalled(); + J.expect(r.onsuccess).toHaveBeenCalled(); + }); + }); + + J.it("should get a key value pair that was added to an object store", function() { + var r = db.transaction([OBJECT_STORE_NAME], IDBTransaction.READ_ONLY) + .objectStore(OBJECT_STORE_NAME) + .get("key"); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; }, "get key" ); + J.runs(function() { J.expect(r.result).toBe("value"); } ); + }); + + J.it("should not add a duplicate key to an object store", function() { + var t = db.transaction([OBJECT_STORE_NAME], IDBTransaction.READ_WRITE); + t.onabort = cast Jasmine.createSpy("007"); + var r = t.objectStore(OBJECT_STORE_NAME).add("value", "key"); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; }, "add duplicate key"); + J.runs(function() { J.expect(t.onabort).toHaveBeenCalled(); } ); + }); + + J.it("should delete a key from an object store", function() { + var r = db.transaction([OBJECT_STORE_NAME], IDBTransaction.READ_WRITE) + .objectStore(OBJECT_STORE_NAME) + .delete("key"); + r.onsuccess = cast Jasmine.createSpy("007"); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; }, "delete key"); + J.runs(function() { J.expect(r.onsuccess).toHaveBeenCalled(); } ); + }); + + J.it("should not get key that was deleted from object store", function() { + var r = db.transaction([OBJECT_STORE_NAME], IDBTransaction.READ_ONLY) + .objectStore(OBJECT_STORE_NAME) + .get("key"); + r.onsuccess = cast Jasmine.createSpy("007"); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; }, "get key" ); + J.runs(function() { + J.expect(r.onsuccess).toHaveBeenCalled(); + J.expect(r.result).not.toBeDefined(); + }); + }); + + J.it("should put a key value pair to an object store", function() { + var r = db.transaction([OBJECT_STORE_NAME], IDBTransaction.READ_WRITE) + .objectStore(OBJECT_STORE_NAME) + .put("value", "key"); + r.onsuccess = cast Jasmine.createSpy("007"); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; }, "put key" ); + J.runs(function() { J.expect(r.onsuccess).toHaveBeenCalled(); } ); + }); + + J.it("should get a key value pair that was put to an object store", function() { + var r = db.transaction([OBJECT_STORE_NAME], IDBTransaction.READ_ONLY) + .objectStore(OBJECT_STORE_NAME) + .get("key"); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; }, "get key" ); + J.runs(function() { J.expect(r.result).toBe("value"); } ); + }); + + J.it("should put an existing key value pair to an object store", function() { + var r = db.transaction([OBJECT_STORE_NAME], IDBTransaction.READ_WRITE) + .objectStore(OBJECT_STORE_NAME) + .put("value", "key"); + r.onsuccess = cast Jasmine.createSpy("007"); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; }, "put existing key" ); + J.runs(function() { J.expect(r.onsuccess).toHaveBeenCalled(); } ); + }); + + J.it("should delete an object store", function() { + var r = db.setVersion(DATABASE_VERSION); + r.onsuccess = function(e:Event) { db.deleteObjectStore(OBJECT_STORE_NAME); }; + var spy = J.spyOn(r, "onsuccess").andCallThrough(); + J.waitsFor(function() { return r.readyState == IDBRequest.DONE; } ); + J.runs(function() { J.expect(spy).toHaveBeenCalled(); } ); + }); + + J.it("should close", function() { + db.close(); + }); + + } ); + } +} \ No newline at end of file diff --git a/lib/html5-haxe/webaudio/AudioBuffer.hx b/lib/html5-haxe/webaudio/AudioBuffer.hx new file mode 100644 index 0000000..3405a2e --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioBuffer.hx @@ -0,0 +1,5 @@ + +extern class AudioBuffer { + + +} diff --git a/lib/html5-haxe/webaudio/AudioBufferCallback.hx b/lib/html5-haxe/webaudio/AudioBufferCallback.hx new file mode 100644 index 0000000..c1381ae --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioBufferCallback.hx @@ -0,0 +1,2 @@ + +typedef AudioBufferCallback = Dynamic; diff --git a/lib/html5-haxe/webaudio/AudioBufferSourceNode.hx b/lib/html5-haxe/webaudio/AudioBufferSourceNode.hx new file mode 100644 index 0000000..534ba27 --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioBufferSourceNode.hx @@ -0,0 +1,11 @@ + +extern class AudioBufferSourceNode extends AudioSourceNode { + var buffer : AudioBuffer; + var gain(default,null) : AudioGain; + var playbackRate : AudioParam; + var loop : Bool; + function new() : Void; + function noteOn( when : Float ) : Void; + function noteGrainOn( when : Float, grainOffset : Float, grainDuration : Float ) : Void; + function noteOff( when : Float ) : Void; +} diff --git a/lib/html5-haxe/webaudio/AudioChannelMerger.hx b/lib/html5-haxe/webaudio/AudioChannelMerger.hx new file mode 100644 index 0000000..df8454e --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioChannelMerger.hx @@ -0,0 +1,2 @@ + +extern class AudioChannelMerger extends AudioNode {} diff --git a/lib/html5-haxe/webaudio/AudioChannelSplitter.hx b/lib/html5-haxe/webaudio/AudioChannelSplitter.hx new file mode 100644 index 0000000..84b0f31 --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioChannelSplitter.hx @@ -0,0 +1,3 @@ + +extern class AudioChannelSplitter extends AudioNode { +} diff --git a/lib/html5-haxe/webaudio/AudioContext.hx b/lib/html5-haxe/webaudio/AudioContext.hx new file mode 100644 index 0000000..35c643a --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioContext.hx @@ -0,0 +1,22 @@ + +extern class AudioContext { + var destination(default,null) : AudioDestinationNode; + var sampleRate(default,null) : Float; + var currentTime(default,null) : Float; + var listener(default,null) : AudioListener; + function new() : Void; + @:overload(function(buffer:ArrayBuffer,mixToMono:Bool):Void{}) + function createBuffer( numberOfChannels : Int, length : Int, sampleRate : Float ) : AudioBuffer; + function decodeAudioData( audioData : ArrayBuffer, successCallback : AudioBufferCallback, ?errorCallback : AudioBufferCallback ) : Void; + function createBufferSource() : AudioBufferSourceNode; + function createJavaScriptNode( bufferSize : Int, numberOfInputs : Int, numberOfOutputs : Int ) : JavaScriptAudioNode; + function createAnalyser() : RealtimeAnalyserNode; + function createGainNode() : AudioGainNode; + function createDelayNode() : DelayNode; + function createBiquadFilter() : BiquadFilterNode; + function createPanner() : AudioPannerNode; + function createConvolver() : ConvolverNode; + function createChannelSplitter() : AudioChannelSplitter; + function createChannelMerger() : AudioChannelMerger; + function createDynamicsCompressor() : DynamicsCompressorNode; +} diff --git a/lib/html5-haxe/webaudio/AudioDestinationNode.hx b/lib/html5-haxe/webaudio/AudioDestinationNode.hx new file mode 100644 index 0000000..597527f --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioDestinationNode.hx @@ -0,0 +1,5 @@ + +extern class AudioDestinationNode extends AudioNode { + var numberOfChannels(default,null) : Int; + //function new() : Void; +} diff --git a/lib/html5-haxe/webaudio/AudioGain.hx b/lib/html5-haxe/webaudio/AudioGain.hx new file mode 100644 index 0000000..a0b4c4a --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioGain.hx @@ -0,0 +1,3 @@ + +extern class AudioGain extends AudioParam { +} diff --git a/lib/html5-haxe/webaudio/AudioGainNode.hx b/lib/html5-haxe/webaudio/AudioGainNode.hx new file mode 100644 index 0000000..7e1dd66 --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioGainNode.hx @@ -0,0 +1,5 @@ + +extern class AudioGainNode extends AudioNode { + var gain : AudioGain; + //function new() : Void; +} diff --git a/lib/html5-haxe/webaudio/AudioListener.hx b/lib/html5-haxe/webaudio/AudioListener.hx new file mode 100644 index 0000000..b544f5f --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioListener.hx @@ -0,0 +1,10 @@ + +extern class AudioListener { + var gain : Float; + var dopplerFactor : Float; + var speedOfSound : Float; + function new() : Void; + function setPosition( x : Float, y : Float, z : Float ) : Void; + function setOrientation( x : Float, y : Float, z : Float, xUp : Float, yUp : Float, zUp : Float ) : Void; + function setVelocity( x : Float, y : Float, z : Float ) : Void; +} diff --git a/lib/html5-haxe/webaudio/AudioNode.hx b/lib/html5-haxe/webaudio/AudioNode.hx new file mode 100644 index 0000000..d034ffa --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioNode.hx @@ -0,0 +1,9 @@ + +extern class AudioNode { + var context(default,null) : AudioContext; + var numberOfInputs(default,null) : Int; + var numberOfOutputs(default,null) : Int; + function new() : Void; + function connect( destination : AudioNode, ?output : Int, ?input : Int ) : Void; + function disconnect( ?output : Int ) : Void; +} diff --git a/lib/html5-haxe/webaudio/AudioPannerNode.hx b/lib/html5-haxe/webaudio/AudioPannerNode.hx new file mode 100644 index 0000000..23ee440 --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioPannerNode.hx @@ -0,0 +1,21 @@ + +extern class AudioPannerNode extends AudioNode { + + static var EQUALPOWER(default,null) : Int; + static var HRTF(default,null) : Int; + static var SOUNDFIELD(default,null) : Int; + + var distanceModel : Int; + var refDistance : Float; + var maxDistance : Float; + var rolloffFactor : Float; + + var coneInnerAngle : Float; + var coneOuterAngle : Float; + var coneOuterGain : Float; + + var coneGain(default,null) : AudioGain; + var distanceGain(default,null) : AudioGain; + + function new() : Void; +} diff --git a/lib/html5-haxe/webaudio/AudioParam.hx b/lib/html5-haxe/webaudio/AudioParam.hx new file mode 100644 index 0000000..22b1bc6 --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioParam.hx @@ -0,0 +1,16 @@ + +extern class AudioParam { + var value : Float; + var minValue(default,null) : Float; + var maxValue(default,null) : Float; + var defaultValue(default,null) : Float; + var name(default,null) : String; + var units(default,null) : Int; + function new() : Void; + function setValueAtTime( value : Float, time : Float ) : Void; + function linearRampToValueAtTime( value : Float, time : Float ) : Void; + function exponentialRampToValueAtTime( value : Float, time : Float ) : Void; + function setTargetValueAtTime( targetValue : Float, time : Float, timeConstant : Float ) : Void; + function setValueCurveAtTime( values : Array, time : Float, duration : Float ) : Void; + function cancelScheduledValues( startTime : Float ) : Void; +} diff --git a/lib/html5-haxe/webaudio/AudioSourceNode.hx b/lib/html5-haxe/webaudio/AudioSourceNode.hx new file mode 100644 index 0000000..a80b1c5 --- /dev/null +++ b/lib/html5-haxe/webaudio/AudioSourceNode.hx @@ -0,0 +1,3 @@ + +extern class AudioSourceNode extends AudioNode { +} diff --git a/lib/html5-haxe/webaudio/BiquadFilterNode.hx b/lib/html5-haxe/webaudio/BiquadFilterNode.hx new file mode 100644 index 0000000..6aefb13 --- /dev/null +++ b/lib/html5-haxe/webaudio/BiquadFilterNode.hx @@ -0,0 +1,16 @@ + +extern class BiquadFilterNode extends AudioNode { + static var LOWPASS(default,null) : Int; + static var HIGHPASS(default,null) : Int; + static var BANDPASS(default,null) : Int; + static var LOWSHELF(default,null) : Int; + static var HIGHSHELF(default,null) : Int; + static var PEAKING(default,null) : Int; + static var NOTCH(default,null) : Int; + static var ALLPASS(default,null) : Int; + var type : Int; + var frequency(default,null) : AudioParam; + var Q(default,null) : AudioParam; + var typegain(default,null) : AudioParam; + function new() : Void; +} diff --git a/lib/html5-haxe/webaudio/ConvolverNode.hx b/lib/html5-haxe/webaudio/ConvolverNode.hx new file mode 100644 index 0000000..224cd1f --- /dev/null +++ b/lib/html5-haxe/webaudio/ConvolverNode.hx @@ -0,0 +1,4 @@ + +extern class ConvolverNode extends AudioNode { + var buffer : AudioBuffer; +} diff --git a/lib/html5-haxe/webaudio/DelayNode.hx b/lib/html5-haxe/webaudio/DelayNode.hx new file mode 100644 index 0000000..37faafc --- /dev/null +++ b/lib/html5-haxe/webaudio/DelayNode.hx @@ -0,0 +1,5 @@ + +extern class DelayNode extends AudioNode { + var delayTime : AudioParam; + //function new() : Void; +} diff --git a/lib/html5-haxe/webaudio/DynamicsCompressorNode.hx b/lib/html5-haxe/webaudio/DynamicsCompressorNode.hx new file mode 100644 index 0000000..707bc62 --- /dev/null +++ b/lib/html5-haxe/webaudio/DynamicsCompressorNode.hx @@ -0,0 +1,2 @@ + +extern class DynamicsCompressorNode extends AudioNode {} diff --git a/lib/html5-haxe/webaudio/JavaScriptAudioNode.hx b/lib/html5-haxe/webaudio/JavaScriptAudioNode.hx new file mode 100644 index 0000000..2a20902 --- /dev/null +++ b/lib/html5-haxe/webaudio/JavaScriptAudioNode.hx @@ -0,0 +1,5 @@ + +extern class JavaScriptAudioNode extends AudioNode { + var onaudioprocess : Dynamic; //TODO EventListener; + var bufferSize(default,null) : Int; +} diff --git a/lib/html5-haxe/webaudio/RealtimeAnalyserNode.hx b/lib/html5-haxe/webaudio/RealtimeAnalyserNode.hx new file mode 100644 index 0000000..1a2dc57 --- /dev/null +++ b/lib/html5-haxe/webaudio/RealtimeAnalyserNode.hx @@ -0,0 +1,11 @@ + +extern class RealtimeAnalyserNode extends AudioNode { + var fftSize : Int; + var frequencyBinCount(default,null) : Int; + var minDecibels : Int; + var maxDecibels : Int; + var smoothingTimeConstant : Int; + function getFloatFrequencyData( array : Array ) : Void; + function getByteFrequencyData( array : Array ) : Void; + function getByteTimeDomainData( array : Array ) : Void; +} diff --git a/lib/html5-haxe/webrtc/LocalMediaStream.hx b/lib/html5-haxe/webrtc/LocalMediaStream.hx new file mode 100644 index 0000000..c586816 --- /dev/null +++ b/lib/html5-haxe/webrtc/LocalMediaStream.hx @@ -0,0 +1,4 @@ + +extern class LocalMediaStream extends MediaStream { + static function stop() : Void; +} diff --git a/lib/html5-haxe/webrtc/MediaStream.hx b/lib/html5-haxe/webrtc/MediaStream.hx new file mode 100644 index 0000000..f3e3441 --- /dev/null +++ b/lib/html5-haxe/webrtc/MediaStream.hx @@ -0,0 +1,11 @@ + +extern class MediaStream { + + static var LIVE(default,null) : Int; + static var ENDED(default,null) : Int; + + static var label(default,null) : String; + static var tracks(default,null) : Array; //MediaStreamTrackList; + + static function record() : MediaStreamRecorder; +} diff --git a/lib/html5-haxe/webrtc/MediaStreamRecorder.hx b/lib/html5-haxe/webrtc/MediaStreamRecorder.hx new file mode 100644 index 0000000..77592d5 --- /dev/null +++ b/lib/html5-haxe/webrtc/MediaStreamRecorder.hx @@ -0,0 +1,4 @@ + +extern class MediaStreamRecorder { + static function getRecordedData( cb : Blob->Void ) : Void; +} diff --git a/lib/html5-haxe/webrtc/NavigatorUserMedia.hx b/lib/html5-haxe/webrtc/NavigatorUserMedia.hx new file mode 100644 index 0000000..63e499e --- /dev/null +++ b/lib/html5-haxe/webrtc/NavigatorUserMedia.hx @@ -0,0 +1,5 @@ + +extern class NavigatorUserMedia { + static function getUserMedia( options : String, success_cb : , ?error_cb : ) : Void; + +} diff --git a/lib/html5-haxe/webrtc/NavigatorUserMediaError.hx b/lib/html5-haxe/webrtc/NavigatorUserMediaError.hx new file mode 100644 index 0000000..3bf42c9 --- /dev/null +++ b/lib/html5-haxe/webrtc/NavigatorUserMediaError.hx @@ -0,0 +1,5 @@ + +extern class NavigatorUserMediaError { + static var PERMISSION_DENIED(default,null) : Int; + static var code(default,null) : Int; +} diff --git a/lib/html5-haxe/webrtc/NavigatorUserMediaErrorCallback.hx b/lib/html5-haxe/webrtc/NavigatorUserMediaErrorCallback.hx new file mode 100644 index 0000000..6f5cf27 --- /dev/null +++ b/lib/html5-haxe/webrtc/NavigatorUserMediaErrorCallback.hx @@ -0,0 +1,4 @@ + +extern class NavigatorUserMediaErrorCallback { + function handleEvent( error : NavigatorUserMediaError ) : Void; +} diff --git a/lib/html5-haxe/webrtc/PeerConnection.hx b/lib/html5-haxe/webrtc/PeerConnection.hx new file mode 100644 index 0000000..b586637 --- /dev/null +++ b/lib/html5-haxe/webrtc/PeerConnection.hx @@ -0,0 +1,44 @@ + +//TODO +@:native("webkitDeprecatedPeerConnection") extern class PeerConnection { + + static var NEW(default,never) : Int; + static var NEGOTIATING(default,never) : Int; + static var ACTIVE(default,never) : Int; + static var CLOSING(default,never) : Int; + static var CLOSED(default,never) : Int; + + static var ICE_GATHERING(default,never) : Int; + static var ICE_WAITING(default,never) : Int; + static var ICE_CHECKING (default,never) : Int; + static var ICE_CONNECTED (default,never) : Int; + static var ICE_COMPLETED(default,never) : Int; + static var ICE_FAILED(default,never) : Int; + static var ICE_CLOSED(default,never) : Int; + + static var SDP_IDLE(default,never) : Int; + static var SDP_WAITING(default,never) : Int; + static var SDP_GLARE(default,never) : Int; + + static var sdpState(default,never) : Int; + + var readyState(default,never) : Int; + var iceState(default,never) : Int; + + var localStreams(default,null) : Array; + var remoteStreams(default,null) : Array; + + var onconnecting : Void->Void; + var onopen : Void->Void; + var onstatechange : Void->Void; + var onaddstream : Dynamic->Void; + var onremovestream : Void->Void; + + function new( configuration : String, signalingCallback : String->Void ) : Void; //TODO SignalingCallback + + function addStream( stream : MediaStream ) : Void; + function removeStream( stream : MediaStream ) : Void; + function close() : Void; + function processSignalingMessage( message : String ) : Void; + +} diff --git a/lib/janicek-core-haxe b/lib/janicek-core-haxe deleted file mode 160000 index 0b03671..0000000 --- a/lib/janicek-core-haxe +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0b03671a60c7b96d5801b9e97332ff5b91836884 diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/MIT.LICENSE b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/MIT.LICENSE new file mode 100644 index 0000000..25412e7 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/MIT.LICENSE @@ -0,0 +1,24 @@ +Janicek Core Haxe +My personal collection of Haxe core libraries. +Copyright (c) 2012 Richard Janicek, http://www.janicek.co + +The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/README.md b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/README.md new file mode 100644 index 0000000..3125a50 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/README.md @@ -0,0 +1,67 @@ +janicek-core-haxe +----------------- + +My personal collection of Haxe core libraries. + +Functional style preferred: +* Modularity through simple data types and simple functions. +* Functions are organized into "core" libraries using static classes. +* Libraries are designed to be used as mix-ins. +* Favor pure functions, avoid state and side effects. +* Favor readability and modularity over performance. +* Functions that take many parameters are ok. +* Favor passing parameters by value, and immutability. +* Functions that have reference parameter types can mutate the parameters, but should always return the mutated parameter reference. Callers of these functions should not depend on the parameter mutations but should only depend on the returned values. This will make it easier to add immutability should Haxe ever support it without sacrificing performance now. + +Tested with Haxe 3.0, JavaScript, and Node.js. + +See [spec classes](https://github.com/rjanicek/janicek-core-haxe/tree/master/test/src/specs/co/janicek/core) for examples of how to use the libraries. + +API docs -> http://rjanicek.github.com/janicek-core-haxe/api + +browser tests -> http://rjanicek.github.com/janicek-core-haxe + +GitHub -> https://github.com/rjanicek/janicek-core-haxe + +###Examples +```haxe +using co.janicek.core.FamilyCore; +using co.janicek.core.LambdaCore; +using co.janicek.core.NullCore; +using co.janicek.core.StringCore; +using Lambda; + +class MainDemo{ + public static function main() { + + trace("NullCore".isNull()); // false + trace("NullCore".isNotNull()); // true + trace(NullCore.coalesce(null, "Hobbit")); // Hobbit + trace([null, "Bilbo", "Hobbit"].coalesceIter()); // Bilbo + + var hobbit : {name : String, parent : Dynamic, children : Array} = null; + + if (hobbit.isNull()) { + hobbit = { + name : "Drogo", + parent : null, + children: [] + }; + } + + var frodo = { + name : "Frodo", + parent : hobbit + } + + hobbit.children.push(frodo); + + trace(hobbit.family().count()); // 2 + trace(hobbit.descendants().count()); // 1 + trace(frodo.lineage().count()); // 2 + trace(frodo.lineage().map(function(h) { return h.name; } ).array()); // [ 'Frodo', 'Drogo' ] + trace(hobbit.family().first(function(h) { return h.name.contains("odo"); }).name); // Frodo + + } +} +``` \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/BaseCode64.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/BaseCode64.hx new file mode 100644 index 0000000..2f31c06 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/BaseCode64.hx @@ -0,0 +1,83 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core; +import haxe.crypto.BaseCode; +import haxe.io.Bytes; +import haxe.io.BytesData; + +class BaseCode64 { + + private static inline var BASE_64_ENCODINGS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + private static inline var BASE_64_PADDING = "="; + + public static function base64EncodeBytesData( bytesData : BytesData ) : String { + var bytes = Bytes.ofData(bytesData); + var encodings = Bytes.ofString(BASE_64_ENCODINGS); + var base64 = new BaseCode(encodings).encodeBytes(bytes).toString(); + + var remainder = base64.length % 4; + + if (remainder > 1) { + base64 += BASE_64_PADDING; + } + + if (remainder == 2) { + base64 += BASE_64_PADDING; + } + + return base64; + } + + public static function base64DecodeBytesData( base64 : String ) : BytesData { + var paddingSize = -1; + if (base64.charAt(base64.length - 2) == BASE_64_PADDING) { + paddingSize = 2; + } + else if (base64.charAt(base64.length - 1) == BASE_64_PADDING) { + paddingSize = 1; + } + + if (paddingSize != -1) { + base64 = base64.substr(0, base64.length - paddingSize); + } + + var encodings = Bytes.ofString(BASE_64_ENCODINGS); + var bytes = new BaseCode(encodings).decodeBytes(Bytes.ofString(base64)); + return bytes.getData(); + } + + public static function base64EncodeString( string : String ) : String { + var bytesData = Bytes.ofString(string).getData(); + return BaseCode64.base64EncodeBytesData(bytesData); + } + + public static function base64DecodeString( base64 : String ) : String { + return Bytes.ofData((BaseCode64.base64DecodeBytesData(base64))).toString(); + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/Constants.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/Constants.hx new file mode 100644 index 0000000..c4c1659 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/Constants.hx @@ -0,0 +1,51 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core; + +/** + * Constants + * @author Richard Janicek + */ + +class Constants { + public static inline var SECONDS_PER_MINUTE = 60; + public static inline var SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR; + public static inline var SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY; + public static inline var MINUTES_PER_HOUR = 60; + public static inline var HOURS_PER_DAY = 24; + + /** + * @see http://en.wikipedia.org/wiki/Kibibyte + */ + public static inline var BYTES_IN_KIBIBYTE = 1024; + public static inline var BYTES_IN_MEBIBYTE = 1024 * BYTES_IN_KIBIBYTE; + + public static var UPPERCASE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + public static var LOWERCASE_ALPHABET = "abcdefghijklmnopqrstuvwxyz"; + public static var DIGITS = "0123456789"; +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/EnumCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/EnumCore.hx new file mode 100644 index 0000000..98f87cb --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/EnumCore.hx @@ -0,0 +1,22 @@ +package co.janicek.core; + +/** + * ... + * @author Richard Janicek + */ +class EnumCore{ + + /** + * Parse string into Enum. If result is undefined, return null. + */ + public static function parseEnum( e : Enum, constr : String, ?params : Array ) : Null { + var result : T = null; + try { + result = Type.createEnum(e, constr, params); + } + catch (error : Dynamic){ + } + return result; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/FamilyCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/FamilyCore.hx new file mode 100644 index 0000000..f2035b8 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/FamilyCore.hx @@ -0,0 +1,138 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core; + +using co.janicek.core.FamilyCore; +using co.janicek.core.LambdaCore; +using Reflect; + +/** + * Functions for objects that have parent / child or tree structures. + * Objects should have a "parent" object and "children" Array. + * Lineages are terminated by a null parent. + * @author Richard Janicek + */ +class FamilyCore { + + /** + * Detect the root node. + */ + public static function isRoot( node : {parent : Null} ) : Bool { + return node.parent == null; + } + + /** + * Get the root node. + */ + public static function root( node : T ) : T { + // TODO: when Haxe >2.10, add type constraint "root}>( node : T ) : T" + + return node.lineage().first(function(n) { + // TODO: when Haxe >2.10, remove untyped + return untyped n.parent == null; + }); + } + + /** + * Lineage iterator. + * Iterates parent objects until null is reached. + * + * + * TODO: Detect and throw on circular references. + */ + public static function lineage( node : T ) : Iterable { + // TODO: when Haxe >2.10, add type constraint "lineage}>( node : T ) : Iterable" + // see: http://code.google.com/p/haxe/issues/detail?id=516 + + return { iterator: function() { + return { + hasNext : function() : Bool { + return node != null; + }, + next : function() : T { + var current = node; + // TODO: when haxe >2.10, remove untyped + untyped node = node.parent; + return current; + } + }; + }}; + } + + /** + * Family iterator. + * Recursively iterates every node in a family including the parent node. + * Nodes may have a field called children : Array. + */ + public static function family( parent : T ) : Iterable { + var stack = new Array(); + stack.push(parent); + return { iterator: function() { + return { + hasNext : function() : Bool { + return stack.length > 0; + }, + next : function() : T { + var node = stack.pop(); + if (node.hasField("children")) { + stack = stack.concat(untyped node.children); + } + return node; + } + }; + }}; + } + + /** + * Descendants iterator. + * Recursively iterates every node that is a descendant of the parent node. + * Nodes may have a field called children : Array. + */ + public static function descendants( parent : T ) : Iterable { + var stack = new Array(); + var loadStack = function(node : T) { + if (node.hasField("children")) { + stack = stack.concat(untyped node.children); + } + } + loadStack(parent); + return { iterator: function() { + return { + hasNext : function() : Bool { + return stack.length > 0; + }, + next : function() : T { + var n = stack.pop(); + loadStack(n); + return n; + } + }; + }}; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/HashTableCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/HashTableCore.hx new file mode 100644 index 0000000..7fbac59 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/HashTableCore.hx @@ -0,0 +1,77 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core; + +using co.janicek.core.StringCore; +using Lambda; + +/** + * Hash table functions. + * @author Richard Janicek + */ +class HashTableCore { + + public static inline var DEFAULT_KEY_VALUE_DELIMETER = "="; + public static inline var DEFAULT_KEY_VALUE_DELIMETER_REGEX_PATTERN = DEFAULT_KEY_VALUE_DELIMETER; + public static inline var DEFAULT_KEY_VALUE_PAIR_DELIMETER = "&"; + public static inline var DEFAULT_KEY_VALUE_PAIR_DELIMETER_REGEX_PATTERN = DEFAULT_KEY_VALUE_PAIR_DELIMETER; + + /** + * Parse a string into a hash table using regular expression patterns for delimeters. + */ + public static function parseHashTable( rawHashTable : String, keyValueDelimeterRegexPattern = DEFAULT_KEY_VALUE_DELIMETER_REGEX_PATTERN, pairDelimeterRegexPattern = DEFAULT_KEY_VALUE_PAIR_DELIMETER_REGEX_PATTERN ) : Map { + var hashTable = new Map(); + + if (!rawHashTable.isNullOrEmpty()) { + var keyValueSplitter = new EReg(keyValueDelimeterRegexPattern, ""); + + new EReg(pairDelimeterRegexPattern, "").split(rawHashTable).iter(function(rawKeyValuePair) { + var item = keyValueSplitter.split(rawKeyValuePair); + if (item.length == 1) { + hashTable.set(item[0], ""); + } + else if (item.length > 1) { + hashTable.set(item[0], item[1]); + } + }); + } + + return hashTable; + } + + /** + * Serialize a hash table into a string using delimeters. + */ + public static function stringifyHashTable( ht : Map < String, String > , keyValueDelimeter = DEFAULT_KEY_VALUE_DELIMETER, pairDelimeter = DEFAULT_KEY_VALUE_PAIR_DELIMETER ) : String { + return { iterator: function(){return ht.keys();} }.fold(function(key, buf : String) { + var value = ht.get(key); + return (buf.isEmpty() ? "" : buf + pairDelimeter) + key + (value.isNullOrEmpty() ? "" : keyValueDelimeter + value); + }, ""); + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/LambdaCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/LambdaCore.hx new file mode 100644 index 0000000..550e0fa --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/LambdaCore.hx @@ -0,0 +1,48 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core; + +/** + * Extra Lambda functions. + * @author Richard Janicek + */ + +class LambdaCore { + + /** + * Returns the first element matching the function f. + */ + public static function first( it : Iterable>, f : Null -> Bool ) : Null { + for (x in it) + if (f(x)) + return x; + + return null; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/NullCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/NullCore.hx new file mode 100644 index 0000000..4c2cb70 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/NullCore.hx @@ -0,0 +1,70 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core; + +using co.janicek.core.NullCore; +using co.janicek.core.LambdaCore; + +/** + * Functions for nulls. + * @author Richard Janicek + */ + +class NullCore { + + /** + * Tests if nullable type is null. + */ + public static inline function isNull( nullable : Null ) : Bool { + return nullable == null; + } + + /** + * Tests if nullable type is not null. + */ + public static inline function isNotNull( nullable : Null ) : Bool { + return nullable != null; + } + + /** + * Coalesce a nullable type using a default value. + * @return Value of nullable type if it's not null else default value. + */ + public static inline function coalesce( nullable : Null, defaultValue : Null ) : Null { + return nullable.isNull() ? defaultValue : nullable; + } + + /** + * Coalesce a list of nullable type. + * @return Value of first non null in list else null. + */ + public static function coalesceIter( nullables : Iterable> ) : Null { + return nullables.first(function(n) { return n.isNotNull(); } ); + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/PathCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/PathCore.hx new file mode 100644 index 0000000..fdfcf12 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/PathCore.hx @@ -0,0 +1,68 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core; + +using StringTools; +using co.janicek.core.StringCore; + +class PathCore { + + /** + * @param pathDelimeter (default = "/") + */ + public static function getDirectoryName( path : String, pathDelimeter = "/" ) : String { + return path.substr(0, path.lastIndexOf(pathDelimeter)); + } + + /** + * @param pathDelimeter (default = "/") + */ + public static function getFileName( path : String, pathDelimeter = "/" ) : String { + var fragments = path.split(pathDelimeter); + return fragments[fragments.length - 1]; + } + + /** + * @param fileExtensionDelimeter (default = ".") + */ + public static function removeFileNameExtension( path : String, fileExtensionDelimeter = "." ) : String { + return path.split(fileExtensionDelimeter)[0]; + } + + /** + * Aggressively remove caracters that might be invalid for a filename. + */ + public static function makeSafeFilename( fileName : String ) : String { + if (fileName.isNullOrEmpty()) { + return ""; + } + var r = ~/[^A-Za-z0-9 _\-\.]/g; + return r.replace(fileName, ""); + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/StringCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/StringCore.hx new file mode 100644 index 0000000..aa9cc1e --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/StringCore.hx @@ -0,0 +1,139 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core; + +using co.janicek.core.LambdaCore; +using co.janicek.core.NullCore; +using co.janicek.core.StringCore; +using Lambda; + +class StringCore { + + /** + * Remove pattern from end of string. + * @param string String to remove pattern from. + * @param pattern String to remove from end of other string. + * @return String with pattern removed from end. + */ + public static function removeFromEnd( string : String, pattern : String ) : String { + if (StringTools.endsWith(string, pattern)) { + return string.substr(0, string.lastIndexOf(pattern)); + } + return string; + } + + + /** + * Test if string contains another string. + * @param search String to test. + * @param pattern Pattern to find in test string. + * @param ignoreCase Ignore case when searching for pattern? default = false + * @return True if string contains pattern, else false. + */ + public static function contains( string : String, pattern : String, ignoreCase = false ) : Bool { + if (ignoreCase) { + string = string.toLowerCase(); + pattern = pattern.toLowerCase(); + } + return string.indexOf(pattern) != -1; + } + + /** + * Test if sting is empty. + * @return True if string is empty. + */ + public static inline function isEmpty( string : String ) : Bool { + return string.length == 0; + } + + /** + * Test if sting is null or empty. + * @return True if string is null or empty. + */ + public static inline function isNullOrEmpty( string : Null ) : Bool { + return (string.isNull() || string.isEmpty()); + } + + /** + * Test if sting is not null or empty. + * @return True if string is not null or empty. + */ + public static inline function isNotNullOrEmpty( string : Null ) : Bool { + return !string.isNullOrEmpty(); + } + + /** + * Find first string that is not null or empty. + * @return First string that is not null or empty or null if none found. + */ + public static function firstNotNullOrEmpty( strings : Iterable> ) : Null { + return strings.first(function(s) { + return s.isNotNullOrEmpty(); + }); + } + + /** + * Test string for Integer value. + * @param s String to test. + * @return True if string is an Integer, else false. + */ + public static function isInteger( s : String ) : Bool { + if (s.contains(".")) return false; + return Std.parseInt(s) != null; + } + + /** + * Wraps a string to a given number of characters. + * @param text The text to wrap. + * @param width The number of characters at which the string will be wrapped. + * @param cut If the cut is set to TRUE, the string is always wrapped at or before the specified width. So if you have a word that is larger than the given width, it is broken apart. + * @return Original text as an array of strings each wrapped to width. + */ + public static function wordWrap( text : String, width = 75, cut = false ) : Array { + + var textLines = text.split("\n"); + + var wordWrappedLines = new Array(); + + textLines.iter(function(line) { + if (line.length == 0) { + wordWrappedLines.push(line); + } + else { + var regex = new EReg(".{1," +width + "}(\\s|$)" + (cut ? "|.{" +width + "}|.+$" : "|\\S+?(\\s|$)"), "g"); + + while (regex.match(line)) { + wordWrappedLines.push(regex.matched(0)); + line = regex.matchedRight(); + } + } + }); + return wordWrappedLines; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dCore.hx new file mode 100644 index 0000000..b9113fe --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dCore.hx @@ -0,0 +1,134 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.array; + +/** + * ... + * @author Richard Janicek + */ + +class Array2dCore { + + /** + * Get value at index. + */ + public static function get( a : Array>, x : Int, y : Int) : T { + if (a[y] == null) { + return null; + } + return a[y][x]; + } + + /** + * Set value at index. + */ + public static function set( a : Array>, x : Int, y : Int, value : T ) : Array> { + if (a[y] == null) { + a[y] = new Array(); + } + a[y][x] = value; + return a; + } + + /** + * Compute two dimensional indices of a flat index based on array width and block size. + */ + public static function getIndices( index : Int, width : Int, blockSize = 1 ) : Array2dIndex { + return { + x : Std.int(index / blockSize) % width, + y : Std.int((index / blockSize) / width) + } + } + + public static function foreachY( a : Array>, f : Array -> Void ) : Void { + for (y in a) { + if (y != null) { + f(y); + } + } + } + + public static function foreachXY( a : Array>, f : Int -> Int -> T -> Void) : Void { + for (yIndex in 0...a.length) { + if (a[yIndex] != null) { + for (xIndex in 0...a[yIndex].length) { + var value = a[yIndex][xIndex]; + if (value != null) { + f(xIndex, yIndex, value); + } + } + + } + } + } + + public static function any( a : Array>, f : T -> Bool ) : Array2dIndex { + for (yIndex in 0...a.length) { + if (a[yIndex] != null) { + for (xIndex in 0...a[yIndex].length) { + var value = a[yIndex][xIndex]; + if (value != null) { + if (f(value)) { + return {x:xIndex, y:yIndex }; + }; + } + } + } + } + return null; + } + + /** + * Get dimensions of array. + */ + public static function dimensions( array : Array> ) : Array2dIndex { + var height = array.length; + var width = 0; + + foreachY(array, function(y:Array):Void { + width = cast Math.max(width, y.length); + } ); + + return {x:width, y:height}; + } + + /** + * Returns an iterator of the 2D Array values. + */ + public static function values( array : Array> ) : Iterable { + return { iterator: function() { return new Array2dValueIterator(array); }} + } + + /** + * Returns an iterator of the 2D Array indexes. + */ + public static function indexes( array : Array> ) : Iterable { + return { iterator: function() { return new Array2dIterator(array); }} + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dIndex.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dIndex.hx new file mode 100644 index 0000000..fea7e33 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dIndex.hx @@ -0,0 +1,38 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.array; + +/** + * ... + * @author Richard Janicek + */ + +typedef Array2dIndex = { + x:Int, + y:Int +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dIterator.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dIterator.hx new file mode 100644 index 0000000..accb10a --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dIterator.hx @@ -0,0 +1,78 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.array; + +using co.janicek.core.array.Array2dCore; + +/** + * ... + * @author Richard Janicek + */ + +class Array2dIterator { + var a:Array>; + var nextValue : Array2dIndex; + var y:Int; + var x:Int; + + public function new(a:Array>) { + this.a = a; + y = 0; + x = 0; + nextValue = null; + } + + public function hasNext():Bool { + if (nextValue != null) { + return true; + } + + while (y < a.length) { + if (a[y] != null) { + while (x < a[y].length && a[y][x] == null) { + x++; + } + if (a[y][x] != null) { + nextValue = { x:x, y:y }; + x++; + return true; + } + x = 0; + } + y++; + } + + return false; + } + + public function next():Array2dIndex { + var n = nextValue; + nextValue = null; + return n; + } +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dValueIterator.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dValueIterator.hx new file mode 100644 index 0000000..51ca541 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/Array2dValueIterator.hx @@ -0,0 +1,76 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.array; + +/** + * ... + * @author Richard Janicek + */ + +class Array2dValueIterator { + var yIterator : Iterator>; + var xIterator : Iterator; + var nextValue : T; + + public function new(a:Array>) { + yIterator = a.iterator(); + xIterator = null; + nextValue = null; + } + + public function hasNext():Bool { + if (nextValue != null) { + return true; + } + + if (xIterator != null) { + while (xIterator.hasNext()) { + nextValue = xIterator.next(); + if (nextValue != null) { + return true; + } + } + } + + while (yIterator.hasNext()) { + var z = yIterator.next(); + if (z != null) { + xIterator = z.iterator(); + return hasNext(); + } + } + + return false; + } + + public function next():T { + var n = nextValue; + nextValue = null; + return n; + } +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/ArrayCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/ArrayCore.hx new file mode 100644 index 0000000..7b818ea --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/array/ArrayCore.hx @@ -0,0 +1,66 @@ +package co.janicek.core.array; + +/** + * Array Functions. + * @author Richard Janicek + */ + +class ArrayCore { + + /** + * Get first element of array. + */ + public static inline function first( a : Array ) : T { + return a[0]; + } + + /** + * Get last element of array. + */ + public static inline function last( a : Array ) : T { + return a[a.length - 1]; + } + + /** + * Moves an array element toward the start of the array with optional wrapping. + */ + public static function moveTowardStart(a : Array, index : Int, wrap = true) : Array { + + if (a.length < 2 || index < 0 || index > a.length - 1) { + return a; + } + + if (index == 0) { + if (wrap) { + a.push(a.shift()); + } + } + else { + a.insert(index - 1, a.splice(index, 1)[0]); + } + + return a; + } + + /** + * Moves an array element toward the end of the array with optional wrapping. + */ + public static function moveTowardEnd(a : Array, index : Int, wrap = true) : Array { + + if (a.length < 2 || index < 0 || index > a.length - 1) { + return a; + } + + if (index == a.length - 1) { + if (wrap) { + a.unshift(a.pop()); + } + } + else { + a.insert(index + 1, a.splice(index, 1)[0]); + } + + return a; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/CanvasCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/CanvasCore.hx new file mode 100644 index 0000000..c95e449 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/CanvasCore.hx @@ -0,0 +1,256 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.html; + +import co.janicek.core.array.Array2dCore; +import co.janicek.core.math.MathCore; +import html5.Canvas; +import html5.CanvasPixelArray; +import html5.CanvasRenderingContext2D; +import html5.File; +import html5.FileReader; +import html5.Image; +import html5.ImageData; +import js.Browser; + +using co.janicek.core.array.Array2dCore; +using co.janicek.core.html.CanvasCore; +using co.janicek.core.math.MathCore; +using co.janicek.core.math.RandomCore; +using Std; + +/** + * Functions for working with HTML Canvas. + * @author Richard Janicek + */ + +class CanvasCore { + + public static inline var CANVAS_ELEMENTS_PER_PIXEL = 4; + public static inline var CANVAS_RED_OFFSET = 0; + public static inline var CANVAS_GREEN_OFFSET = 1; + public static inline var CANVAS_BLUE_OFFSET = 2; + public static inline var CANVAS_ALPHA_OFFSET = 3; + + /** + * Iterate canvas pixel array color channels. + * Functor is called with red, green, blue, and alpha channel values for each pixel. + * Functor can return new color channel values which will be assigned to pixel. Null values are ignored. + * + * Can be used to analyze and transform a canvas pixel array. + */ + public static function renderCanvasPixelArray( imageData : ImageData, f : Int -> Int -> Int -> Int -> Int -> Null<{red : Null, green : Null, blue : Null, alpha : Null}> ) : Void { + var pixels = imageData.data; + var index:Int; + for (i in 0...Std.int(pixels.length / CANVAS_ELEMENTS_PER_PIXEL)) { + index = i * CANVAS_ELEMENTS_PER_PIXEL; + var newValues = f(index, pixels[index + CANVAS_RED_OFFSET], pixels[index + CANVAS_GREEN_OFFSET], pixels[index + CANVAS_BLUE_OFFSET], pixels[index + CANVAS_ALPHA_OFFSET]); + if (newValues != null) { + if (newValues.red != null) { + pixels[index + CANVAS_RED_OFFSET] = newValues.red; + } + if (newValues.green != null) { + pixels[index + CANVAS_GREEN_OFFSET] = newValues.green; + } + if (newValues.blue != null) { + pixels[index + CANVAS_BLUE_OFFSET] = newValues.blue; + } + if (newValues.alpha != null) { + pixels[index + CANVAS_ALPHA_OFFSET] = newValues.alpha; + } + } + } + } + + /** + * Add random noise to image data by modifying each pixel color channel by a random amount between + and - noiseLevel. + * @param noiseLevel Value between 1 and 255 + * @param grayScale True to change all color channels by same amount so only brightness of pixel is changed and not color. Doesn't affect alpha. (Default = false) + * @param red Add noise to red channel. (Default = true) + * @param green Add noise to green channel. (Default = true) + * @param blue Add noise to blue channel. (Default = true) + * @param alpha Add noise to alpha channel. (Default = false) + * @return New bitmap containing the bitmap passed in with noise added. + */ + public static function addNoise( pixelData : ImageData, randomSeed : Int, noiseLevel : Int, grayScale = false, changeRed = true, changeGreen = true, changeBlue = true, changeAlpha = false) : ImageData { + noiseLevel = MathCore.clampInt(noiseLevel, 1, 255); + var delta:Int; + + renderCanvasPixelArray(pixelData, function(index, red, green, blue, alpha) { + delta = (randomSeed = randomSeed.nextParkMiller()).toIntRange( -noiseLevel, noiseLevel); + var newColors = { red:null, green:null, blue:null, alpha:null }; + if (changeRed) { + newColors.red = red + delta; + } + if (changeGreen) { + newColors.green = green + (grayScale ? delta : (randomSeed = randomSeed.nextParkMiller()).toIntRange( -noiseLevel, noiseLevel)); + } + if (changeBlue) { + newColors.blue = blue + (grayScale ? delta : (randomSeed = randomSeed.nextParkMiller()).toIntRange( -noiseLevel, noiseLevel)); + } + if (changeAlpha) { + newColors.alpha = alpha + (randomSeed = randomSeed.nextParkMiller()).toIntRange( -noiseLevel, noiseLevel); + } + return newColors; + }); + + return pixelData; + } + + /** + * Add noise to canvas. + * @param context Canvas drawing context. + * @param randomSeed Random seed to use to make random noise. + * @param noiseLevel Value between 1 and 255 + * @param grayScale True to change all color channels by same amount so only brightness of pixel is changed and not color. Doesn't affect alpha. (Default = false) + * @param red Add noise to red channel. (Default = true) + * @param green Add noise to green channel. (Default = true) + * @param blue Add noise to blue channel. (Default = true) + * @param alpha Add noise to alpha channel. (Default = false) + */ + public static function addNoiseToCanvas( context : CanvasRenderingContext2D, randomSeed : Int, noiseLevel : Int, grayScale = false, red = true, green = true, blue = true, alpha = false) : Void { + var imageData = context.getImageData(0, 0, context.canvas.width, context.canvas.height); + imageData = addNoise(imageData, randomSeed, noiseLevel, grayScale, red, green, blue, alpha); + context.putImageData(imageData, 0, 0); + } + + // ------------------------------------------------------------------------ + // Images + + /** + * Load an image from a URL. + * @param url Image to load. + * @param f Called when image is loaded. + */ + public static function loadImage( url : String, f : Image -> Void ) : Void { + var image:Image = new Image(); + image.onload = function() { + f(image); + } + image.src = url; + } + + /** + * Load a file into an image. + */ + public static function loadFileIntoImage( file : File, img : Image ) : Void { + var reader = new FileReader(); + reader.onload = function(event) { + img.src = event.target.result; + } + reader.readAsDataURL(file); + } + + /** + * Get image data from an HTML image. + */ + public static function getImageData( image : Image ) : ImageData { + var canvas:Canvas = cast Browser.document.createElement("canvas"); + canvas.width = image.width; + canvas.height = image.height; + var ctx = canvas.getContext("2d"); + ctx.drawImage(image, 0, 0); + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + return imageData; + } + + /** + * Make image data URL from image data. + */ + public static function makeImageDataUrlFromImageData( imageData : ImageData ) : String { + var canvas:Canvas = cast Browser.document.createElement("canvas"); + canvas.width = imageData.width.int(); + canvas.height = imageData.height.int(); + canvas.getContext("2d").putImageData(imageData, 0, 0); + return canvas.toDataURL(); + } + + // ------------------------------------------------------------------------ + // Monochrome Converters + + /** + * Converts HTML5 image data to monochrome image data by comparing the average of each color channel to a + * threshold value to determine which color channels are converted to target monochrome colors. + * @param threshold Value between 0 and 255. + * @param lessthanThresholdColor Color to use for pixels below threshold. + * @param greaterthanOrEqualToThresholdColor Color to use for pixels equal to or above threshold. + * @param alpha Optioal alpha to assign to result pixels. (default = 1.0) + */ + public static function makeAverageThresholdImageData( imageData : ImageData, threshold : Int, lessthanThresholdColor : Int, greaterthanOrEqualToThresholdColor : Int, alpha = 1.0) : ImageData { + var intAlpha = HtmlColorCore.colorFraction(alpha); + imageData.renderCanvasPixelArray(function(index, red, green, blue, alpha) { + var color = [red, green, blue].averageInt() >= threshold ? greaterthanOrEqualToThresholdColor : lessthanThresholdColor; + return { + red : HtmlColorCore.getRedComponent(color), + green : HtmlColorCore.getGreenComponent(color), + blue : HtmlColorCore.getBlueComponent(color), + alpha : intAlpha + } + }); + return imageData; + } + + /** + * Convert image to monochrome bitmap boolean array. + * Converts HTML5 image data to a 2D Array of Bool by comparing the average of each color channel to a + * threshold value to determine which color channels are converted to 0 and 1. + * @param threshold Value between 0 and 255. + */ + public static function makeAverageThresholdBitmap( imageData : ImageData, threshold : Int ) : Array> { + threshold = threshold.clampInt(0, 255); + return makeBitmap(imageData, function(red, green, blue, alpha) { + return [red, green, blue].averageInt() >= threshold; + }); + } + + /** + * Make a boolean array from html image data. + */ + public static function makeBitmap( imageData : ImageData, f : Int -> Int -> Int -> Int -> Bool ) : Array> { + var array = new Array>(); + renderCanvasPixelArray(imageData, function(index, red, green, blue, alpha) { + var indices = Array2dCore.getIndices(index, Std.int(imageData.width), CANVAS_ELEMENTS_PER_PIXEL); + array.set(indices.x, indices.y, f(red, green, blue, alpha)); + return null; + }); + return array; + } + + /** + * Inverts an array of bool. + * @param bitmap Array of bool to invert. + * @return Inverted array of bool. + */ + public static function invertBitmap( bitmap : Array> ) : Array> { + bitmap.foreachXY(function (x, y, value) { + bitmap.set(x, y, !value); + }); + return bitmap; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/Console.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/Console.hx new file mode 100644 index 0000000..51316c5 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/Console.hx @@ -0,0 +1,46 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.html; + +/** + * Console API + * @see http://getfirebug.com/wiki/index.php/Console_API + */ + +@:native("console") +extern class Console { + public static function assert( expression : Dynamic ) : Void; + public static function count( ?title : String) : Void; + public static function debug( object : Dynamic ) : Void; + public static function dir( object : Dynamic ) : Void; + public static function error( object : Dynamic ) : Void; + public static function info( object : Dynamic ) : Void; + public static function log( object : Dynamic ) : Void; + public static function trace() : Void; + public static function warn( object : Dynamic ) : Void; +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/HtmlColor.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/HtmlColor.hx new file mode 100644 index 0000000..8ae4faa --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/HtmlColor.hx @@ -0,0 +1,64 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.html; + +/** + * HTML Color constructors. + * @see http://www.w3schools.com/cssref/css_colornames.asp + * @author Richard Janicek + */ + +enum HtmlColor { + /** + * Make a color from an integer value. + */ + Color( color : Int ); + Rgb( r : Int, g : Int, b : Int ); + Rgba( red : Int, green : Int, blue : Int, alpha : Float ); + RgbF( red : Float, green : Float, blue : Float ); + RgbaF( red : Float, green : Float, blue : Float, alpha : Float ); + Hsl( hue : Int, saturation : Float, lightness : Float ); + Hsla( hue : Int, saturation : Float, lightness : Float, alpha : Float ); +} + +class HtmlColors { + /** + * Convert HtmlColor to string. + */ + public static function toString( c : HtmlColor ) : String { + return switch (c) { + case Color(c) : HtmlColorCore.intToHexColor(c); + case Rgb(r, g, b) : HtmlColorCore.rgb(r, g, b); + case Rgba(r, g, b, a) : HtmlColorCore.rgba(r, g, b, a); + case RgbF(r, g, b) : HtmlColorCore.rgbF(r, g, b); + case RgbaF(r, g, b, a) : HtmlColorCore.rgbaF(r, g, b, a); + case Hsl(h, s, l): HtmlColorCore.hsl(h, s, l); + case Hsla(h, s, l, a): HtmlColorCore.hsla(h, s, l, a); + } + } +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/HtmlColorCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/HtmlColorCore.hx new file mode 100644 index 0000000..6103e16 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/html/HtmlColorCore.hx @@ -0,0 +1,157 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.html; + +using co.janicek.core.math.MathCore; +using Std; + +/** + * Color functions. + * @author Richard Janicek + */ +class HtmlColorCore { + + public static inline var MAX_COLOR_COMPONENT = 0xff; + + /** + * Get red component of Int color. + */ + public static inline function getRedComponent( c : Int ) : Int { + return (c >> 16) & 0xff; + } + + /** + * Get green component of Int color. + */ + public static inline function getGreenComponent( c : Int ) : Int { + return (c >> 8) & 0xff; + } + + /** + * Get blue component of Int color. + */ + public static inline function getBlueComponent( c : Int ) : Int { + return c & 0xff; + } + + /** + * Interpolate color between color0 and color1 using fraction f. When f==0, result is color0. When f==1, result is color1. + * @author Amit Patel + */ + public static function interpolateColor( color0 : Int, color1 : Int, f : Float ) : Int { + var r:Int = Std.int((1 - f) * (color0 >> 16) + f * (color1 >> 16)); + var g:Int = Std.int((1 - f) * ((color0 >> 8) & 0xff) + f * ((color1 >> 8) & 0xff)); + var b:Int = Std.int((1 - f) * (color0 & 0xff) + f * (color1 & 0xff)); + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + return (r << 16) | (g << 8) | b; + } + + /** + * Convert a fraction (0.0 - 1.0) to a color value (0 - 0xff). + */ + public static inline function colorFraction( fraction : Float ) : Int { + return (MAX_COLOR_COMPONENT * fraction).int(); + } + + /** + * Make HTML hex color string from Int value. Example: 0 -> #000000 + * @param color Int color value. + * @return HTML color string. + */ + public static function intToHexColor( color : Int ) : String { + return "#" + StringTools.hex(color, 6); + } + + /** + * Make HTML rgb(r,g,b,a) color string. + * @param red Red channel (0 - 0xff). + * @param green Green channel (0 - 0xff). + * @param blue Blue channel (0 - 0xff). + */ + public static function rgb( red : Int, green : Int, blue : Int ) : String { + return 'rgb($red,$green,$blue)'; + } + + /** + * Make HTML rgba(r,g,b,a) color string. + * @param red Red channel (0 - 0xff). + * @param green Green channel (0 - 0xff). + * @param blue Blue channel (0 - 0xff). + * @param alpha Alpha channel (0.0 - 1.0). + */ + public static function rgba( red : Int, green : Int, blue : Int, alpha : Float) : String { + return 'rgba($red,$green,$blue,$alpha)'; + } + + /** + * Make HTML rgb(r,g,b) color string using fractions. + * @param red Red channel (0.0 - 1.0). + * @param green Green channel (0.0 - 1.0). + * @param blue Blue channel (0.0 - 1.0). + */ + public static function rgbF( red : Float, green : Float, blue : Float ) : String { + return 'rgb(${red*100}%,${green*100}%,${blue*100}%)'; + } + + /** + * Make HTML rgba(r,g,b,a) color string using fractions. + * @param red Red channel (0.0 - 1.0). + * @param green Green channel (0.0 - 1.0). + * @param blue Blue channel (0.0 - 1.0). + * @param alpha Alpha channel (0.0 - 1.0). + */ + public static function rgbaF( red : Float, green : Float, blue : Float, alpha : Float) : String { + return 'rgba(${red*100}%,${green*100}%,${blue*100}%,$alpha)'; + } + + /** + * Make HTML hsl(h,s,l) color string. + * @param hue A degree on the color wheel (from 0 to 360) - 0 (or 360) is red, 120 is green, 240 is blue. + * @param saturation A percentage value; 0.0 means a shade of gray and 1.0 is the full color. + * @param lightness Lightness is also a percentage; 0.0 is black, 1.0 is white. + * @return HTML color string. + */ + public static function hsl(hue : Int, saturation : Float, lightness : Float) : String { + return 'hsl($hue,${saturation*100}%,${lightness*100}%)'; + } + + /** + * Make HTML hsla(h,s,l,a) color string. + * @param hue A degree on the color wheel (from 0 to 360) - 0 (or 360) is red, 120 is green, 240 is blue. + * @param saturation A percentage value; 0.0 means a shade of gray and 1.0 is the full color. + * @param lightness Lightness is also a percentage; 0.0 is black, 1.0 is white. + * @param alpha Number between 0.0 (fully transparent) and 1.0 (fully opaque). + * @return HTML color string. + */ + public static function hsla( hue : Int, saturation : Float, lightness : Float, alpha : Float) : String { + return 'hsla($hue,${saturation*100}%,${lightness*100}%,$alpha)'; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/HttpCookieCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/HttpCookieCore.hx new file mode 100644 index 0000000..1de19ae --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/HttpCookieCore.hx @@ -0,0 +1,53 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.http; + +using co.janicek.core.HashTableCore; +using Reflect; + +/** + * HTTP Cookie functions. + * @see http://en.wikipedia.org/wiki/HTTP_cookie + * @author Richard Janicek + */ +class HttpCookieCore { + + public static inline var COOKIE_PAIR_DELIMETER_REGEX_PATTERN = "[;,] "; + public static inline var COOKIE_KEY_VALUE_DELIMETER = "="; + + /** + * Parse raw cookie string into a hash table key=cookie-name value=cookie-value. + * Works for cookies with "; " or ", " delimeters. + * @param rawCookies + * @return Hash table of cookies. + */ + public static function parseCookies( rawCookies : String ) : Map { + return rawCookies.parseHashTable(COOKIE_KEY_VALUE_DELIMETER, COOKIE_PAIR_DELIMETER_REGEX_PATTERN); + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/MailTo.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/MailTo.hx new file mode 100644 index 0000000..b2f3e18 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/MailTo.hx @@ -0,0 +1,65 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2013 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.janicek.core.http; + +using Std; +using StringTools; + +/** + * @see http://en.wikipedia.org/wiki/Mailto + */ +class MailTo{ + + /** + * Create a mailto: link. + */ + public static function createLink( to : Array, subject = "", body = "", ?cc : Array ) : String { + var href = ["mailto:${to.join(',')}".format()]; + var parameters = []; + + if (cc != null) { + parameters.push("cc=${to.join(',').urlEncode}".format()); + } + + if (subject.length > 0) { + parameters.push("subject=${subject.urlEncode()}".format()); + } + + if (body.length > 0) { + parameters.push("body=${body.urlEncode()}".format()); + } + + if (parameters.length > 0) { + href.push(parameters.join("&")); + } + + return href.join("?") ; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/UrlCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/UrlCore.hx new file mode 100644 index 0000000..80324e2 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/http/UrlCore.hx @@ -0,0 +1,175 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.http; +import haxe.ds.GenericStack; + +using co.janicek.core.NullCore; +using co.janicek.core.HashTableCore; +using co.janicek.core.StringCore; +using Reflect; +using Lambda; +using Std; + +/** + * Parts of a URL. + */ +typedef Url = { + source : String, + protocol : String, + authority : String, + userInfo : String, + user : String, + password : String, + host : String, + port : String, + relative : String, + path : String, + directory : String, + file : String, + query : String, + fragment : String +} + +/** + * Functions related to URL's. + * @see http://en.wikipedia.org/wiki/Url + * @author Richard Janicek + */ +class UrlCore { + public static inline var URL_QUERY_DELIMETER = "?"; + public static inline var URL_FRAGMENT_DELIMETER = "#"; + public static inline var KEY_VALUE_DELIMETER = "="; + public static inline var KEY_VALUE_PAIR_DELIMETER = "&"; + + public static function makeEmptyUrl() : Url { + return { + source : "", + protocol : "", + authority : "", + userInfo : "", + user : "", + password : "", + host : "", + port : "", + relative : "", + path : "", + directory : "", + file : "", + query : "", + fragment : "" + } + } + + /** + * Parse a URL string into it's parts. + * @see http://en.wikipedia.org/wiki/URI_scheme + */ + public static function parseUrl( url : String ) : Url { + var urlParts = makeEmptyUrl(); + + // The almighty regexp (courtesy of http://blog.stevenlevithan.com/archives/parseuri) + var r : EReg = ~/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; + + // Match the regexp to the url + r.match(url); + + // Use reflection to set each part + var i = 0; + for (field in urlParts.fields()) { + var part = r.matched(i).coalesce(""); + urlParts.setField(field, part); + i++; + } + + return urlParts; + } + + /** + * Parse a URL query into a struct object. + * Duplicate keys are stored as arrays. + * The caller can store the result in a strongly typed struct: eg: typedef Query = { id : String, item : Array } + */ + public static function parseUrlQuery( query : String ) : Dynamic { + if (query.charAt(0) == URL_QUERY_DELIMETER) { + query = query.substr(1); + } + return parseKeyValuePairsToStruct(query, KEY_VALUE_DELIMETER, KEY_VALUE_PAIR_DELIMETER); + } + + /** + * Parse a URL fragment into a struct object. + * Duplicate keys are stored as arrays. + * The caller can store the result in a strongly typed struct: eg: typedef Fragment = { id : String, item : Array } + */ + public static function parseUrlFragment( fragment : String ) : Dynamic { + if (fragment.charAt(0) == URL_FRAGMENT_DELIMETER) { + fragment = fragment.substr(1); + } + return parseKeyValuePairsToStruct(fragment, KEY_VALUE_DELIMETER, KEY_VALUE_PAIR_DELIMETER); + } + + /** + * Parse a string into a struct object using regular expression patterns for delimeters. + * Duplicate keys are stored as arrays. + * The caller can store the result in a strongly typed struct: eg: typedef Fragment = { id : String, item : Array } + */ + public static function parseKeyValuePairsToStruct( delimetedData : String, keyValueDelimeterRegexPattern = KEY_VALUE_DELIMETER, pairDelimeterRegexPattern = KEY_VALUE_PAIR_DELIMETER ) : Dynamic { + var struct = { }; + + if (!delimetedData.isNullOrEmpty()) { + var keyValueSplitter = new EReg(keyValueDelimeterRegexPattern, ""); + + new EReg(pairDelimeterRegexPattern, "g").split(delimetedData).iter(function(delimetedData) { + var item = keyValueSplitter.split(delimetedData); + if (struct.hasField(item[0])) { + if (!struct.field(item[0]).is(Array)) { + var a = new Array(); + a.push(struct.field(item[0])); + struct.setField(item[0], a); + } + struct.field(item[0]).push(item.length > 1 ? item[1] : ""); + } + else { + struct.setField(item[0], item.length > 1 ? item[1] : ""); + } + }); + } + + return struct; + } + + public static function stringifyStructToKeyValuePairs( map : {}, keyValueDelimeter = KEY_VALUE_DELIMETER, pairDelimeter = KEY_VALUE_PAIR_DELIMETER ) : String { + var fields = new Array(); + for (field in map.fields()) { + fields.push(field + keyValueDelimeter + StringTools.urlEncode(map.field(field))); + } + return fields.join(pairDelimeter); + } + + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/macro/Resource.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/macro/Resource.hx new file mode 100644 index 0000000..07bb73a --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/macro/Resource.hx @@ -0,0 +1,41 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2013 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.macro; + +import haxe.macro.Context; + +class Resource{ + + /** + * Embed a file into source code as a string. + */ + macro public static function embedFileAsString( file : String ) { + return Context.makeExpr(sys.io.File.getContent(file), Context.currentPos()); + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/GeometryCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/GeometryCore.hx new file mode 100644 index 0000000..4a304e3 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/GeometryCore.hx @@ -0,0 +1,35 @@ +package co.janicek.core.math; + +/** + * ... + * @author Richard Janicek + */ +class GeometryCore{ + + /** + * Centers one rectangle on another and returns it's top, left coordinates. + */ + public static function getCenterRectangles( anchorTop : Float, anchorLeft : Float, anchorWidth : Float, anchorHeight : Float, + movableTop : Float, movableLeft : Float, movableWidth : Float, movableHeight : Float ) : { left : Float, top : Float } { + + var anchorCenterY = anchorTop + (anchorHeight / 2); + var anchorCenterX = anchorLeft + (anchorWidth / 2); + var movableCenterY = movableTop + (movableHeight / 2); + var movableCenterX = movableLeft + (movableWidth / 2); + return {left : anchorCenterX - movableCenterX, top : anchorCenterY - movableCenterY}; + } + + /** + * Constrain a rectangle to maximum dimensions with optional aspect ratio preservation. + */ + public static function fitRectangle( width : Float, height : Float, maxWidth : Float, maxHeight : Float, preserveAspectRatio = true ) : { width : Float, height : Float } { + var scale = preserveAspectRatio + ? Math.min(width <= maxWidth ? 1 : maxWidth / width, height <= maxHeight ? 1 : maxHeight / height) + : 1; + return { + width : Math.min(width * scale, maxWidth) , + height : Math.min(height * scale, maxHeight) + } + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/HashCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/HashCore.hx new file mode 100644 index 0000000..53ae427 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/HashCore.hx @@ -0,0 +1,82 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.math; + +/** + * Hashing Algorithms + * + * @author Richard Janicek + */ + +class HashCore { + + /** + * Compute string hash using djb2 algorithm. + * + * Has a good balance of being extremely fast, while providing a reasonable distribution of hash values. + * @see http://www.cse.yorku.ca/~oz/hash.html + */ + public static function djb2( s : String ) : Int { + var hash = 5381; + for (i in 0...s.length) { + hash = ((hash << 5) + hash) + s.charCodeAt(i); + } + return hash; + } + + /** + * Compute string hash using sdbm algorithm. + * + * This algorithm was created for sdbm (a public-domain reimplementation of ndbm) database library. + * It was found to do well in scrambling bits, causing better distribution of the keys and fewer splits. + * It also happens to be a good general hashing function with good distribution. + * @see http://www.cse.yorku.ca/~oz/hash.html + */ + public static function sdbm( s : String ) : Int { + var hash = 0; + for (i in 0...s.length) { + hash = s.charCodeAt(i) + (hash << 6) + (hash << 16) - hash; + } + return hash; + } + + /** + * Java's String.hashCode() method implemented in Haxe. + * @see http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#hashCode%28%29 + */ + public static function javaHashCode( s : String ) : Int { + var hash = 0; + if (s.length == 0) return hash; + for (i in 0...s.length) { + hash = ((hash << 5) - hash) + s.charCodeAt(i); + hash = hash & hash; // Convert to 32bit integer + } + return hash; + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/MathCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/MathCore.hx new file mode 100644 index 0000000..b1faa6e --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/MathCore.hx @@ -0,0 +1,120 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.math; + +using co.janicek.core.math.MathCore; +using Lambda; +using Math; +using Std; + +class MathCore { + + /** + * Max value, signed integer. + */ + inline public static var INT32_MAX = 0x7fffffff; + + /** + * Biggest whole number. + * WARNING: WHOLE_NUMBER_MAX + 1 === WHOLE_NUMBER_MAX + * WARNING: bit operations don't work on numbers > INT32_MAX + * @see http://en.wikipedia.org/wiki/IEEE_754-1985 + */ + inline public static var WHOLE_NUMBER_MAX = 9007199254740992; + + /** + * Smallest whole number. + * WARNING: WHOLE_NUMBER_MIN - 1 === WHOLE_NUMBER_MIN + * WARNING: bit operations don't work on numbers < -INT32_MAX + * @see http://en.wikipedia.org/wiki/IEEE_754-1985 + */ + inline public static var WHOLE_NUMBER_MIN = -9007199254740992; + + public static function isEven( n : Int ) : Bool { + return n % 2 == 0; + } + + public static function isOdd( n : Int ) : Bool { + return !isEven(n); + } + + /** + * clamp an Integer to an interval + * interval endpoints are compared to get min and max, so it doesn't matter what order they are passed in + * @param value value to clamp + * @param minOrMax1 interval endpoint + * @param minOrMax2 interval endpoint + * @return clamped value to given interval + */ + public static function clampInt( value : Int, minOrMax1 : Int, minOrMax2 : Int ) : Int { + return value.clamp(minOrMax1, minOrMax2).int(); + } + + /** + * clamp a Float to an interval + * interval endpoints are compared to get min and max, so it doesn't matter what order they are passed in + * @param value value to clamp + * @param minOrMax1 interval endpoint + * @param minOrMax2 interval endpoint + * @return clamped value to given interval + */ + public static function clamp( value : Float, minOrMax1 : Float, minOrMax2 : Float ) : Float { + var min = Math.min(minOrMax1, minOrMax2); + var max = Math.max(minOrMax1, minOrMax2); + return value < min ? min : value > max ? max : value; + } + + public static function degreesToRadians( degrees : Float ) : Float { + return (degrees * Math.PI) / 180; + } + + public static function radiansToDegrees( radians : Float ) : Float { + return (radians * 180) / Math.PI; + } + + public static function average( numbers : Array ) : Float { + return numbers.fold(function(number, total) { + return total + number; + }, 0) / numbers.length; + } + + public static function averageInt( numbers : Array ) : Float { + return numbers.fold(function(number, total) { + return total + number; + }, 0) / numbers.length; + } + + /** + * Calculate the distance between two points. + */ + public static function distance( a : {x : Float, y:Float}, b : {x : Float, y:Float} ) : Float { + return ( (a.x - b.x).pow(2) + + (a.y - b.y).pow(2) ).sqrt(); + } + +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/PerlinNoise.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/PerlinNoise.hx new file mode 100644 index 0000000..b36bfc2 --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/PerlinNoise.hx @@ -0,0 +1,191 @@ +/** +Title: Perlin noise +Version: 1.3 +Author: Ron Valstar +Author URI: http://www.sjeiti.com/ +Original code port from http://mrl.nyu.edu/~perlin/noise/ +and some help from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm +AS3 optimizations by Mario Klingemann http://www.quasimondo.com +Haxe port and optimization by Nicolas Cannasse http://haxe.org +Cross-platform and simplified by Richard Janicek http://janicek.co +*/ +package co.janicek.core.math; +using co.janicek.core.array.Array2dCore; + +class PerlinNoise { + + private static var p = [ + 151,160,137,91,90,15,131,13,201,95, + 96,53,194,233,7,225,140,36,103,30,69, + 142,8,99,37,240,21,10,23,190,6,148, + 247,120,234,75,0,26,197,62,94,252, + 219,203,117,35,11,32,57,177,33,88, + 237,149,56,87,174,20,125,136,171, + 168,68,175,74,165,71,134,139,48,27, + 166,77,146,158,231,83,111,229,122, + 60,211,133,230,220,105,92,41,55,46, + 245,40,244,102,143,54,65,25,63,161, + 1,216,80,73,209,76,132,187,208,89, + 18,169,200,196,135,130,116,188,159, + 86,164,100,109,198,173,186,3,64,52, + 217,226,250,124,123,5,202,38,147,118, + 126,255,82,85,212,207,206,59,227,47, + 16,58,17,182,189,28,42,223,183,170, + 213,119,248,152,2,44,154,163,70,221, + 153,101,155,167,43,172,9,129,22,39, + 253,19,98,108,110,79,113,224,232, + 178,185,112,104,218,246,97,228,251, + 34,242,193,238,210,144,12,191,179, + 162,241,81,51,145,235,249,14,239, + 107,49,192,214,31,181,199,106,157, + 184,84,204,176,115,121,50,45,127,4, + 150,254,138,236,205,93,222,114,67,29, + 24,72,243,141,128,195,78,66,215,61, + 156,180,151,160,137,91,90,15,131,13, + 201,95,96,53,194,233,7,225,140,36, + 103,30,69,142,8,99,37,240,21,10,23, + 190,6,148,247,120,234,75,0,26,197, + 62,94,252,219,203,117,35,11,32,57, + 177,33,88,237,149,56,87,174,20,125, + 136,171,168,68,175,74,165,71,134,139, + 48,27,166,77,146,158,231,83,111,229, + 122,60,211,133,230,220,105,92,41,55, + 46,245,40,244,102,143,54,65,25,63, + 161,1,216,80,73,209,76,132,187,208, + 89,18,169,200,196,135,130,116,188, + 159,86,164,100,109,198,173,186,3,64, + 52,217,226,250,124,123,5,202,38,147, + 118,126,255,82,85,212,207,206,59, + 227,47,16,58,17,182,189,28,42,223, + 183,170,213,119,248,152,2,44,154, + 163,70,221,153,101,155,167,43,172,9, + 129,22,39,253,19,98,108,110,79,113, + 224,232,178,185,112,104,218,246,97, + 228,251,34,242,193,238,210,144,12, + 191,179,162,241,81,51,145,235,249, + 14,239,107,49,192,214,31,181,199, + 106,157,184,84,204,176,115,121,50, + 45,127,4,150,254,138,236,205,93, + 222,114,67,29,24,72,243,141,128, + 195,78,66,215,61,156,180 + ]; + + public static function makePerlinNoise(width:Int, height:Int, _x:Float, _y:Float, _z:Float, seed = 666, octaves = 4, falloff = 0.5, ?_ ) : Array> { + + var baseFactor:Float = 1 / 64; + + var iXoffset = seed = Std.int((seed * 16807.) % 2147483647); + var iYoffset = seed = Std.int((seed * 16807.) % 2147483647); + var iZoffset = seed = Std.int((seed * 16807.) % 2147483647); + + var aOctFreq = []; // frequency per octave + var aOctPers = []; // persistence per octave + var fPersMax = 0.0; // 1 / max persistence + + var fFreq:Float, fPers:Float; + + for ( i in 0...octaves ) { + fFreq = Math.pow(2,i); + fPers = Math.pow(falloff,i); + fPersMax += fPers; + aOctFreq.push( fFreq ); + aOctPers.push( fPers ); + } + + fPersMax = 1 / fPersMax; + + var bitmap = new Array>(); + + var baseX = _x * baseFactor + iXoffset; + _y = _y * baseFactor + iYoffset; + _z = _z * baseFactor + iZoffset; + + for ( py in 0...height ) { + _x = baseX; + + for ( px in 0...width ) { + var s = 0.; + + for ( i in 0...octaves ) { + var fFreq = aOctFreq[i]; + var fPers = aOctPers[i]; + + var x = _x * fFreq; + var y = _y * fFreq; + var z = _z * fFreq; + + var xf = x - (x % 1); + var yf = y - (y % 1); + var zf = z - (z % 1); + + var X = Std.int(xf) & 255; + var Y = Std.int(yf) & 255; + var Z = Std.int(zf) & 255; + + x -= xf; + y -= yf; + z -= zf; + + var u = x * x * x * (x * (x*6 - 15) + 10); + var v = y * y * y * (y * (y*6 - 15) + 10); + var w = z * z * z * (z * (z*6 - 15) + 10); + + var A = (p[X]) + Y; + var AA = (p[A]) + Z; + var AB = (p[A+1]) + Z; + var B = (p[X+1]) + Y; + var BA = (p[B]) + Z; + var BB = (p[B+1]) + Z; + + var x1 = x-1; + var y1 = y-1; + var z1 = z-1; + + var hash = (p[BB+1]) & 15; + var g1 = ((hash&1) == 0 ? (hash<8 ? x1 : y1) : (hash<8 ? -x1 : -y1)) + ((hash&2) == 0 ? hash<4 ? y1 : ( hash==12 ? x1 : z1 ) : hash<4 ? -y1 : ( hash==14 ? -x1 : -z1 )); + + hash = (p[AB+1]) & 15; + var g2 = ((hash&1) == 0 ? (hash<8 ? x : y1) : (hash<8 ? -x : -y1)) + ((hash&2) == 0 ? hash<4 ? y1 : ( hash==12 ? x : z1 ) : hash<4 ? -y1 : ( hash==14 ? -x : -z1 )); + + hash = (p[BA+1]) & 15; + var g3 = ((hash&1) == 0 ? (hash<8 ? x1 : y ) : (hash<8 ? -x1 : -y )) + ((hash&2) == 0 ? hash<4 ? y : ( hash==12 ? x1 : z1 ) : hash<4 ? -y : ( hash==14 ? -x1 : -z1 )); + + hash = (p[AA+1]) & 15; + var g4 = ((hash&1) == 0 ? (hash<8 ? x : y ) : (hash<8 ? -x : -y )) + ((hash&2) == 0 ? hash<4 ? y : ( hash==12 ? x : z1 ) : hash<4 ? -y : ( hash==14 ? -x : -z1 )); + + hash = (p[BB]) & 15; + var g5 = ((hash&1) == 0 ? (hash<8 ? x1 : y1) : (hash<8 ? -x1 : -y1)) + ((hash&2) == 0 ? hash<4 ? y1 : ( hash==12 ? x1 : z ) : hash<4 ? -y1 : ( hash==14 ? -x1 : -z )); + + hash = (p[AB]) & 15; + var g6 = ((hash&1) == 0 ? (hash<8 ? x : y1) : (hash<8 ? -x : -y1)) + ((hash&2) == 0 ? hash<4 ? y1 : ( hash==12 ? x : z ) : hash<4 ? -y1 : ( hash==14 ? -x : -z )); + + hash = (p[BA]) & 15; + var g7 = ((hash&1) == 0 ? (hash<8 ? x1 : y ) : (hash<8 ? -x1 : -y )) + ((hash&2) == 0 ? hash<4 ? y : ( hash==12 ? x1 : z ) : hash<4 ? -y : ( hash==14 ? -x1 : -z )); + + hash = (p[AA]) & 15; + var g8 = ((hash&1) == 0 ? (hash<8 ? x : y ) : (hash<8 ? -x : -y )) + ((hash&2) == 0 ? hash<4 ? y : ( hash==12 ? x : z ) : hash<4 ? -y : ( hash==14 ? -x : -z )); + + g2 += u * (g1 - g2); + g4 += u * (g3 - g4); + g6 += u * (g5 - g6); + g8 += u * (g7 - g8); + + g4 += v * (g2 - g4); + g8 += v * (g6 - g8); + + s += ( g8 + w * (g4 - g8)) * fPers; + } + + var color = Std.int( ( s * fPersMax + 1 ) * 128 ); + + bitmap.set(px, py, 0xff000000 | color << 16 | color << 8 | color ); + + _x += baseFactor; + } + + _y += baseFactor; + } + + return bitmap; + } +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/RandomCore.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/RandomCore.hx new file mode 100644 index 0000000..01496ad --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/RandomCore.hx @@ -0,0 +1,133 @@ +/** + * janicek-core-haxe + * ------------------ + * My personal collection of Haxe core libraries. + * Copyright (c) 2012 Richard Janicek, http://www.janicek.co + * + * The MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package co.janicek.core.math; + +import co.janicek.core.math.MathCore; + +using Std; + +/** + * Pseudo random number generator (PRNG) using a functional style. +*/ +class RandomCore { + + /** + * (a Mersenne prime M31) modulus constant = 2^31 - 1 = 0x7ffffffe + */ + private inline static var MPM = 2147483647.0; + + /** + * (a primitive root modulo M31) + */ + private inline static var MINSTD = 16807.0; + + /** + * Make a non deterministic random seed using standard libraries. + * @return Non deterministic random seed. + */ + public static function makeRandomSeed() : Int { + return Math.floor(Math.random() * MPM); + } + + /** + * Park-Miller-Carta algorithm. + * @see http://lab.polygonal.de/?p=162 + * @see http://code.google.com/p/polygonal/source/browse/trunk/src/lib/de/polygonal/core/math/random/ParkMiller.hx?r=547 + * @see http://en.wikipedia.org/wiki/Lehmer_random_number_generator + * @return Returns the next pseudo-random int value. + */ + public static inline function nextParkMiller( seed : Int ) : Int { + return ((seed * MINSTD) % MPM).int(); + } + + /** + *

A Park-Miller-Carta PRNG (pseudo random number generator).

+ *

Integer implementation, using only 32 bit integer maths and no divisions.

+ * @see POLYGONAL - A HAXE LIBRARY FOR GAME DEVELOPERS + * @see http://www.firstpr.com.au/dsp/rand31/rand31-park-miller-carta.cc.txt + * @see Park-Miller random number generator. + * @see A good Pseudo-Random Number Generator (PRNG). + */ + public static function nextParkMiller31( seed : Int ) : Int { + var lo:Int = 16807 * (seed & 0xffff); + var hi:Int = 16807 * (seed >>> 16); + lo += (hi & 0x7fff) << 16; + lo += hi >>> 15; + if (lo > 0x7fffffff) lo -= 0x7fffffff; + return lo; + } + + /** + * Linear congruential generator using GLIBC constants. + * + * @see http://en.wikipedia.org/wiki/Linear_congruential_generator + * @see https://github.com/aduros/flambe/blob/master/src/flambe/util/Random.hx + * @return Returns an integer in [0, INT_MAX) + */ + public static inline function nextLCG( seed : Int ) : Int { + // These constants borrowed from glibc + // Force float multiplication here to avoid overflow in Flash (and keep parity with JS) + return ((1103515245.0 * seed + 12345) % MPM).int(); + } + + /** + * Returns the pseudo-random double value x in the range 0 <= x < 1. + */ + public static inline function toFloat( seed : Int ) : Float { + return seed / MPM; + } + + /** + * Returns a pseudo-random boolean value (coin flip). + */ + public static inline function toBool( seed : Int ) : Bool { + return toFloat(seed) > 0.5; + } + + /** + * Returns a pseudo-random double value x in the range min <= x <= max. + */ + public static inline function toFloatRange( seed : Int, min : Float, max : Float ) : Float { + return min + (max - min) * toFloat(seed); + } + + /** + * Returns a pseudo-random integral value x in the range min <= x <= max. + */ + public static inline function toIntRange( seed : Int, min : Int, max : Int ) : Int { + return Math.round((min - 0.4999) + ((max + 0.4999) - (min - 0.4999)) * toFloat(seed)); + } + + /** + * Converts a string to a seed. + * Lets you use words as seeds. + */ + public static function stringToSeed( s : String ) : Int { + return (HashCore.djb2(s) % MPM).int(); + } +} \ No newline at end of file diff --git a/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/UUID.hx b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/UUID.hx new file mode 100644 index 0000000..881d51c --- /dev/null +++ b/lib/janicek-core-haxe-6630d81bc734a8886e0156fd3a95e7dd3104bd0a/src/co/janicek/core/math/UUID.hx @@ -0,0 +1,139 @@ +/*! +Math.uuid.js (v1.4) +http://www.broofa.com +mailto:robert@broofa.com + +Copyright (c) 2010 Robert Kieffer +Haxe conversion by Richard Janicek +Dual licensed under the MIT and GPL licenses. +*/ +package co.janicek.core.math; + +using co.janicek.core.math.RandomCore; +using co.janicek.core.NullCore; +using co.janicek.core.math.MathCore; +using Std; +using EReg; +using StringTools; + +/** + * Random universally unique identifier (UUID) generators. + * @see http://en.wikipedia.org/wiki/Uuid + */ +class UUID { + + private static var CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""); + + /** + * Generate a UUID. + * + * EXAMPLES: + * + * One argument - returns ID of the specified length + * >>> uuid(15) // 15 character ID (default base=62) + * "VcydxgltxrVZSTV" + * + * Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62) + * >>> uuid(8, 2) // 8 character ID (base=2) + * "01001010" + * >>> uuid(8, 10) // 8 character ID (base=10) + * "47473046" + * >>> uuid(8, 16) // 8 character ID (base=16) + * "098F4D35" + * + * @param length the desired number of characters + * @param radix the number of allowable values for each character, clamped to [2,62], default = 62 + * @param seed optional PRNG seed + */ + public static function uuid( length : Int, ?radix : Int, ?seed : Int ) { + + if (seed.isNull()) seed = RandomCore.makeRandomSeed(); + var chars = CHARS, uuid = [], i; + radix = radix.coalesce(chars.length).clampInt(2, chars.length); + + for (i in 0...length) uuid[i] = chars[0 | ((seed = seed.nextParkMiller()).toFloat() * radix).int()]; + + return uuid.join(""); + } + + /** + * Generate a UUID using specific characters. + * @param length the desired number of characters + * @param ?characters optional desired characters to use to build the UUID + * @param ?seed optional PRNG seed + */ + public static function uuidChars( length : Int, ?characters : String, ?seed : Int ) { + if (seed.isNull()) + seed = RandomCore.makeRandomSeed(); + var chars = characters.isNull() ? CHARS : characters.split(""); + if (chars.length < 2) + throw "must have at least 2 characters"; + var uuid = []; + var radix = chars.length; + for (i in 0...length) uuid[i] = chars[0 | ((seed = seed.nextParkMiller()).toFloat() * radix).int()]; + return uuid.join(""); + } + + /** + * generate RFC4122, version 4 ID + * example "92329D39-6F5C-4520-ABFC-AAB64544E172" + * @param seed optional PRNG seed + */ + public static function uuidRfc4122V4( ?seed : Int ) { + + if (seed.isNull()) seed = RandomCore.makeRandomSeed(); + var chars = CHARS, uuid = [], i; + + // rfc4122, version 4 form + var r : Int; + + // rfc4122 requires these characters + uuid[8] = uuid[13] = uuid[18] = uuid[23] = "-"; + uuid[14] = "4"; + + // Fill in random data. At i==19 set the high bits of clock sequence as + // per rfc4122, sec. 4.1.5 + for (i in 0...36) { + if (uuid[i].isNull()) { + r = 0 | ((seed = seed.nextParkMiller()).toFloat() * 16).int(); + uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; + } + } + + return uuid.join(""); + } + + /** + * A more performant, but slightly bulkier, RFC4122v4 solution. We boost performance + * by minimizing calls to random() + */ + public static function uuidFast( ?seed : Int ) { + if (seed.isNull()) seed = RandomCore.makeRandomSeed(); + var chars = CHARS, uuid = new Array(), rnd=0, r; + for (i in 0...36) { + if (i==8 || i==13 || i==18 || i==23) { + uuid[i] = "-"; + } else if (i==14) { + uuid[i] = "4"; + } else { + if (rnd <= 0x02) rnd = 0x2000000 + ((seed = seed.nextParkMiller()).toFloat() * 0x1000000).int() | 0; + r = rnd & 0xf; + rnd = rnd >> 4; + uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; + } + } + return uuid.join(""); + } + + /** + * A more compact, but less performant, RFC4122v4 solution: + */ + public static function uuidCompact( ?seed : Int ) { + if (seed.isNull()) seed = RandomCore.makeRandomSeed(); + return new EReg("[xy]", "g").map("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx", function (c) { + var r = ((seed = seed.nextParkMiller()).toFloat() * 16).int() | 0, v = c.matched(0) == "x" ? r : (r & 0x3 | 0x8); + return v.hex(); + }); + } + +} \ No newline at end of file diff --git a/src/as3/NumberCore.hx b/src/as3/NumberCore.hx index a50f2cf..7a240c0 100644 --- a/src/as3/NumberCore.hx +++ b/src/as3/NumberCore.hx @@ -7,7 +7,7 @@ class NumberCore { /** * From JavaScript. */ - public static inline var MIN_VALUE:Number = 5 * Math.pow(10, -324); // 5e-324; - public inline static var MAX_VALUE = 1.7976931348623157 * Math.pow(10, 308); // 1.7976931348623157e+308 + public static inline var MIN_VALUE:Number = 5e-324;// 5 * Math.pow(10, -324); // 5e-324; + public inline static var MAX_VALUE = 1.7976931348623157e+308; // 1.7976931348623157 * Math.pow(10, 308); // 1.7976931348623157e+308 } \ No newline at end of file diff --git a/src/as3/TypeDefs.hx b/src/as3/TypeDefs.hx index bd23b11..33b1367 100644 --- a/src/as3/TypeDefs.hx +++ b/src/as3/TypeDefs.hx @@ -2,7 +2,7 @@ package as3; typedef BitmapData = Array>; typedef Boolean = Bool; -typedef Dictionary = Hash; +typedef Dictionary = Map; typedef Number = Float; typedef Point = { x:Number, y:Number }; typedef UInt = Int; diff --git a/src/as3/Vector3D.hx b/src/as3/Vector3D.hx index 56bf4d5..7029cec 100644 --- a/src/as3/Vector3D.hx +++ b/src/as3/Vector3D.hx @@ -29,12 +29,12 @@ package as3; class Vector3D { - inline public var length(getLength,null):Float; - inline public function getLength():Float { + public var length(get_length,null):Float; + inline public function get_length():Float { return Math.abs(Vector3D.distance(this,new Vector3D())); } - inline public var lengthSquared(getLengthSquared,null):Float; - inline public function getLengthSquared():Float { + public var lengthSquared(get_lengthSquared,null):Float; + inline public function get_lengthSquared():Float { return length * length; } @@ -138,16 +138,16 @@ class Vector3D { return "Vector3D("+x+", "+y+", "+z+")"; } - inline public static var X_AXIS(getX_AXIS,null):Vector3D; - inline public static function getX_AXIS():Vector3D { + public static var X_AXIS(get_X_AXIS,null):Vector3D; + inline public static function get_X_AXIS():Vector3D { return new Vector3D(1,0,0); } - inline public static var Y_AXIS(getY_AXIS,null):Vector3D; - inline public static function getY_AXIS():Vector3D { + public static var Y_AXIS(get_Y_AXIS,null):Vector3D; + inline public static function get_Y_AXIS():Vector3D { return new Vector3D(0,1,0); } - inline public static var Z_AXIS(getZ_AXIS,null):Vector3D; - inline public static function getZ_AXIS():Vector3D { + public static var Z_AXIS(get_Z_AXIS,null):Vector3D; + inline public static function get_Z_AXIS():Vector3D { return new Vector3D(0,0,1); } } diff --git a/src/com/nodename/delaunay/Edge.hx b/src/com/nodename/delaunay/Edge.hx index 78b9b66..5bf1b97 100644 --- a/src/com/nodename/delaunay/Edge.hx +++ b/src/com/nodename/delaunay/Edge.hx @@ -72,9 +72,9 @@ class Edge { //private static const LINESPRITE:Sprite = new Sprite(); //private static const GRAPHICS:Graphics = LINESPRITE.graphics; - public var delaunayLineBmp(getDelaunayLineBmp, never):BitmapData; + public var delaunayLineBmp(get_delaunayLineBmp, never):BitmapData; private var _delaunayLineBmp:BitmapData; - private function getDelaunayLineBmp():BitmapData + private function get_delaunayLineBmp():BitmapData { if (_delaunayLineBmp == null) { @@ -195,8 +195,8 @@ class Edge { public var clippedEnds(default, null):Dictionary; // unless the entire Edge is outside the bounds. // In that case visible will be false: - public var visible(getVisible, never):Boolean; - private inline function getVisible():Boolean + public var visible(get_visible, never):Boolean; + private inline function get_visible():Boolean { return clippedEnds != null; } diff --git a/src/com/nodename/delaunay/EdgeList.hx b/src/com/nodename/delaunay/EdgeList.hx index 226645e..fb2c7ee 100644 --- a/src/com/nodename/delaunay/EdgeList.hx +++ b/src/com/nodename/delaunay/EdgeList.hx @@ -11,14 +11,14 @@ class EdgeList implements IDisposable { private var _hashsize:Int; private var _hash:Vector; private var _leftEnd:Halfedge; - public var leftEnd(getLeftEnd, never):Halfedge; - public inline function getLeftEnd():Halfedge + public var leftEnd(get_leftEnd, never):Halfedge; + public inline function get_leftEnd():Halfedge { return _leftEnd; } private var _rightEnd:Halfedge; - public var rightEnd(getRightEnd, never):Halfedge; - public inline function getRightEnd():Halfedge + public var rightEnd(get_rightEnd, never):Halfedge; + public inline function get_rightEnd():Halfedge { return _rightEnd; } diff --git a/src/com/nodename/delaunay/Site.hx b/src/com/nodename/delaunay/Site.hx index ab909e3..66611f0 100644 --- a/src/com/nodename/delaunay/Site.hx +++ b/src/com/nodename/delaunay/Site.hx @@ -372,13 +372,13 @@ class Site implements ICoord { } } - public var x(getX, null):Number; - private inline function getX():Number + public var x(get_x, null):Number; + private inline function get_x():Number { return _coord.x; } - public var y(getY, null):Number; - private inline function getY():Number + public var y(get_y, null):Number; + private inline function get_y():Number { return _coord.y; } diff --git a/src/com/nodename/delaunay/SiteList.hx b/src/com/nodename/delaunay/SiteList.hx index 8e6f1ac..1b03429 100644 --- a/src/com/nodename/delaunay/SiteList.hx +++ b/src/com/nodename/delaunay/SiteList.hx @@ -40,8 +40,8 @@ class SiteList implements IDisposable { return _sites.push(site); } - public var length(getLength, null):Int; - private inline function getLength():Int + public var length(get_length, null):Int; + private inline function get_length():Int { return _sites.length; } diff --git a/src/com/nodename/delaunay/Vertex.hx b/src/com/nodename/delaunay/Vertex.hx index 342809e..a7cba03 100644 --- a/src/com/nodename/delaunay/Vertex.hx +++ b/src/com/nodename/delaunay/Vertex.hx @@ -114,13 +114,13 @@ class Vertex implements ICoord { return Vertex.create(intersectionX, intersectionY); } - public var x(getX, null):Number; - private inline function getX():Number + public var x(get_x, null):Number; + private inline function get_x():Number { return _coord.x; } - public var y(getY, null):Number; - private inline function getY():Number + public var y(get_y, null):Number; + private inline function get_y():Number { return _coord.y; } diff --git a/src/com/nodename/delaunay/Voronoi.hx b/src/com/nodename/delaunay/Voronoi.hx index 1c8b124..9dc29b9 100644 --- a/src/com/nodename/delaunay/Voronoi.hx +++ b/src/com/nodename/delaunay/Voronoi.hx @@ -66,6 +66,9 @@ class Voronoi { _triangles = new Vector(); _edges = new Vector(); fortunesAlgorithm(); +// for(edge in _edges) { +// trace([edge.a, edge.b, edge.c]); +// } } /** @@ -75,7 +78,7 @@ class Voronoi { * Prevent this case until it's possible to store duplicate points coords. */ private function makeSureNoDuplicatePoints(points:Vector) { - var h = new Hash(); + var h = new Map(); for (p in points) { if (h.exists(p.hash())) { throw "Duplicate points not supported yet!"; diff --git a/src/voronoimap/Main.hx b/src/voronoimap/Main.hx index c92d762..dff76d8 100644 --- a/src/voronoimap/Main.hx +++ b/src/voronoimap/Main.hx @@ -4,7 +4,7 @@ import co.janicek.core.html.CanvasCore; import co.janicek.core.html.HtmlColorCore; import co.janicek.core.math.RandomCore; import de.polygonal.math.PM_PRNG; -import haxe.Firebug; +import haxe.Timer; import html5.Canvas; import html5.CanvasRenderingContext2D; import html5.File; @@ -12,6 +12,7 @@ import html5.FileList; import html5.FileReader; import html5.Image; import html5.typedArrays.ArrayBuffer; +import js.Browser; import js.JQuery; import js.Lib; import voronoimap.html.CanvasRender; @@ -74,7 +75,6 @@ class Main { private static var state : State; static function main() { - Firebug.redirectTraces(); initializeUi(); state = generate(); } @@ -118,8 +118,8 @@ class Main { new JQuery([Html.S_invertImage, Html.S_imageThreshold].toString()).change(function(e) { updateThumb(); } ); - new JQuery(Html.S_width).val(Std.string(Lib.window.innerWidth)); - new JQuery(Html.S_height).val(Std.string(Lib.window.innerHeight)); + new JQuery(Html.S_width).val(Std.string(Browser.window.innerWidth)); + new JQuery(Html.S_height).val(Std.string(Browser.window.innerHeight)); new JQuery(Html.S_view).change(function(e) { switch(new JQuery(Html.S_view).val()) { @@ -161,22 +161,23 @@ class Main { } public static function getContext():CanvasRenderingContext2D { - var canvas:Canvas = cast Lib.document.getElementById(Html.ID_map); + var canvas:Canvas = cast Browser.document.getElementById(Html.ID_map); return canvas.getContext("2d"); } private static function findOrCreateCanvas():Canvas { - var canvas:Canvas = cast Lib.document.getElementById(Html.ID_map); + var canvas:Canvas = cast Browser.document.getElementById(Html.ID_map); if (canvas == null) { - canvas = cast Lib.document.createElement("canvas"); + canvas = cast Browser.document.createElement("canvas"); canvas.id = Html.ID_map; - Lib.document.body.appendChild(canvas); + Browser.document.body.appendChild(canvas); } return canvas; } public static function generate() : State { + var start = Timer.stamp(); var state = { map : null, noisyEdges : null, roads : null, watersheds : null, lava : null }; var canvas = findOrCreateCanvas(); @@ -223,11 +224,22 @@ class Main { state.map.go4AssignMoisture(new JQuery(Html.S_riverChance).val().parseInt()); state.map.go5DecorateMap(); - var thresholds = new JQuery(Html.S_roadElevationThresholds).val().split(",").map(callback(Std.parseFloat)).array(); + var thresholds = new JQuery(Html.S_roadElevationThresholds).val().split(",").map(Std.parseFloat.bind()).array(); state.roads.createRoads(state.map, thresholds); state.watersheds.createWatersheds(state.map); state.noisyEdges.buildNoisyEdges(state.map, state.lava, seed, new JQuery(Html.S_edgeNoise).val().parseFloat()); + + var generateMs = Std.int((Timer.stamp() - start) * 1000); + new JQuery('#generateMs').text(Std.string(generateMs)); + start = Timer.stamp(); + render(state); + + var renderMs = Std.int((Timer.stamp() - start) * 1000); + new JQuery('#renderMs').text(Std.string(renderMs)); + + new JQuery('#totalMs').text(Std.string(renderMs + generateMs)); + return state; } diff --git a/src/voronoimap/Map.hx b/src/voronoimap/Map.hx index 34906d2..2a30673 100644 --- a/src/voronoimap/Map.hx +++ b/src/voronoimap/Map.hx @@ -233,7 +233,6 @@ class Map { // Option 3 is implemented here. If it's run for too many iterations, // it will turn into a grid, but convergence is very slow, and we only // run it a few times. - var i:Int, p:Point, q:Point, voronoi:Voronoi, region:Vector; for (i in 0...numLloydIterations) { voronoi = new Voronoi(points, null, new Rectangle(0, 0, SIZE.width, SIZE.height)); @@ -395,7 +394,7 @@ class Map { edge.index = edges.length; edge.river = 0; edges.push(edge); - edge.midpoint = if(vedge.p0 != null && vedge.p1 != null) PointCore.interpolate(vedge.p0, vedge.p1, 0.5); + edge.midpoint = (vedge.p0 != null && vedge.p1 != null) ? PointCore.interpolate(vedge.p0, vedge.p1, 0.5) : null; // Edges point to corners. Edges point to centers. edge.v0 = makeCorner(vedge.p0); diff --git a/src/voronoimap/html/CanvasRender.hx b/src/voronoimap/html/CanvasRender.hx index 464cdc0..8e10cfc 100644 --- a/src/voronoimap/html/CanvasRender.hx +++ b/src/voronoimap/html/CanvasRender.hx @@ -84,7 +84,7 @@ class CanvasRender { var B:Vector3D = new Vector3D(r.point.x, r.point.y, r.elevation); var C:Vector3D = new Vector3D(s.point.x, s.point.y, s.elevation); var normal:Vector3D = B.subtract(A).crossProduct(C.subtract(A)); - if (normal.z < 0) { normal.scaleBy(-1); } + if (normal.z < 0) { normal.scaleBy( -1); } normal.normalize(); var light:Number = 0.5 + 35*normal.dotProduct(lightVector); if (light < 0) light = 0; @@ -95,6 +95,7 @@ class CanvasRender { public static function colorWithSlope(color:Int, p:Center, q:Center, edge:Edge, displayColors:DisplayColors):Int { var r:Corner = edge.v0; var s:Corner = edge.v1; + if (r.isNull() || s.isNull()) { // Edge of the map return displayColors.OCEAN; @@ -102,7 +103,10 @@ class CanvasRender { return color; } - if (q != null && p.water == q.water) color = HtmlColorCore.interpolateColor(color, Reflect.field(displayColors, q.biome), 0.4); + if (q != null && p.water == q.water) { + color = HtmlColorCore.interpolateColor(color, Reflect.field(displayColors, q.biome), 0.4); + } + var colorLow:Int = HtmlColorCore.interpolateColor(color, 0x333333, 0.7); var colorHigh:Int = HtmlColorCore.interpolateColor(color, 0xffffff, 0.3); var light:Number = calculateLighting(p, r, s); @@ -269,6 +273,7 @@ class CanvasRender { } if (gradientFillProperty != null) { + // We'll draw two triangles: center - corner0 - // midpoint and center - midpoint - corner1. var corner0:Corner = edge.v0; diff --git a/test/src/Main.hx b/test/src/Main.hx index 1170bca..ca96782 100644 --- a/test/src/Main.hx +++ b/test/src/Main.hx @@ -1,4 +1,3 @@ -import haxe.Firebug; import jasmine.Jasmine; import js.Lib; import specs.AS3Spec; @@ -11,8 +10,7 @@ import specs.VoronoiSpec; class Main { static function main() { - Firebug.redirectTraces(); - trace(Std.format("Testing...")); + trace("Testing..."); new AS3Spec(); new ConversionCoreSpec(); diff --git a/test/src/specs/MapSpec.hx b/test/src/specs/MapSpec.hx index 092cfd0..baf5949 100644 --- a/test/src/specs/MapSpec.hx +++ b/test/src/specs/MapSpec.hx @@ -1,5 +1,7 @@ package specs; +import haxe.Json; +import haxe.Serializer; import jasmine.J; import voronoimap.IslandShape; import voronoimap.Lava; @@ -27,18 +29,19 @@ class MapSpec { map.go0PlacePoints(numPoints); J.expect(map.points.length).toBe(numPoints); }); - + J.it("should improve points", function() { map.go1ImprovePoints(); + J.expect(map.points.length).toBe(numPoints); }); J.it("should build a graph", function() { map.go2BuildGraph(); +trace('map.corners.length', map.corners.length); map.assignBiomes(); J.expect(true).toBeTruthy(); }); - J.it("should add features", function() { map.go3AssignElevations(); map.go4AssignMoisture(); diff --git a/test/src/specs/VoronoiSpec.hx b/test/src/specs/VoronoiSpec.hx index 428d187..b622677 100644 --- a/test/src/specs/VoronoiSpec.hx +++ b/test/src/specs/VoronoiSpec.hx @@ -19,7 +19,7 @@ class VoronoiSpec { J.it("should make voronoi", function() { var r = 1; var points = new Vector(); - for (i in 0...100) { + for (i in 0...5) { var x = ((r = r.nextParkMiller()).toFloatRange(1, 99)); var y = ((r = r.nextParkMiller()).toFloatRange(1, 99)); var p = { x:x, y:y }; diff --git a/voronoi-map-haxe.hxproj b/voronoi-map-haxe.hxproj index 37e5a83..bba4ed2 100644 --- a/voronoi-map-haxe.hxproj +++ b/voronoi-map-haxe.hxproj @@ -16,7 +16,7 @@ - + @@ -26,7 +26,7 @@