├── patching-system ├── server │ ├── filelist.json │ ├── patches │ │ └── 0.zip │ └── httpd.py ├── build │ ├── 0 │ │ ├── lena.png │ │ ├── kodim01.png │ │ └── kodim19.png │ ├── 1 │ │ ├── lena.png │ │ ├── kodim01.png │ │ ├── kodim19.png │ │ └── arch0 │ │ │ ├── lena.png │ │ │ ├── kodim01.png │ │ │ └── kodim19.png │ ├── 300 │ │ ├── kerp.jpg │ │ ├── lena.png │ │ ├── kodim01.png │ │ └── kodim19.png │ └── gen_patch.py └── client │ └── client.py ├── canvas-pixel-picking ├── 0.png ├── 1.png ├── 2.png ├── 3.png ├── httpd.py ├── index.html └── core.js ├── canvas-faster-picking ├── client │ ├── 0.png │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── index.html │ └── core.js └── tools │ ├── bin │ ├── textures │ │ ├── 0.png │ │ ├── 1.png │ │ ├── 2.png │ │ └── 3.png │ ├── FreeImagePlus.dll │ └── builddata.bat │ └── hullgen │ ├── FreeImage.h │ ├── FreeImage.lib │ ├── GenSpriteHull.suo │ ├── contrib │ └── FreeImagePlus │ │ ├── FreeImagePlus.dll │ │ ├── FreeImagePlus.h │ │ └── FreeImagePlus.lib │ ├── GenSpriteHull.sln │ ├── imgHelper.h │ ├── imgHelper.cpp │ ├── GenSpriteHull.vcproj │ ├── main.cpp │ └── LICENSE.txt ├── canvas_tiled_rendering ├── data │ ├── grits_master.png │ ├── map.tmx │ └── largeLevel.tmx ├── Readme.md ├── index.html ├── 0_forward │ ├── index.html │ └── TILEDmap.js ├── 2_refresh_tiling │ ├── index.html │ └── TILEDmap.js ├── 1_grits_tiling │ ├── index.html │ └── TILEDmap.js ├── mrdoob-stats.js ├── httpd.py ├── coreGame.js └── core.js ├── stat_tracker ├── 0.simple │ ├── gae_launch.bat │ ├── app.yaml │ ├── index.html │ └── main.py ├── 1.client-gather │ ├── gae_launch.bat │ ├── app.yaml │ ├── index.html │ └── main.py └── 2.server-gather │ ├── grits_gae_launch.bat │ ├── backends.yaml │ ├── app.yaml │ ├── ah_start_backend.py │ ├── stats_backend.py │ ├── index.html │ └── main.py ├── chrome-event-trace ├── HOWTO.txt ├── event_trace.cpp ├── win_test │ └── main.cpp ├── event_trace_plat.h └── event_trace_impl.h └── needle.js ├── tests ├── perf_base.html ├── depth_test.html ├── perf_console_time.html ├── perf_needle_disabled.html ├── perf_needle_coarse.html ├── perf_needle_fine.html └── perf_needle_orig.html ├── Readme.md └── needle.js /patching-system/server/filelist.json: -------------------------------------------------------------------------------- 1 | {"builds": [{"buildnum": 0, "add-files": ["0.zip"]} ]} -------------------------------------------------------------------------------- /canvas-pixel-picking/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-pixel-picking/0.png -------------------------------------------------------------------------------- /canvas-pixel-picking/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-pixel-picking/1.png -------------------------------------------------------------------------------- /canvas-pixel-picking/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-pixel-picking/2.png -------------------------------------------------------------------------------- /canvas-pixel-picking/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-pixel-picking/3.png -------------------------------------------------------------------------------- /patching-system/build/0/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/0/lena.png -------------------------------------------------------------------------------- /patching-system/build/1/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/1/lena.png -------------------------------------------------------------------------------- /canvas-faster-picking/client/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/client/0.png -------------------------------------------------------------------------------- /canvas-faster-picking/client/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/client/1.png -------------------------------------------------------------------------------- /canvas-faster-picking/client/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/client/2.png -------------------------------------------------------------------------------- /canvas-faster-picking/client/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/client/3.png -------------------------------------------------------------------------------- /patching-system/build/0/kodim01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/0/kodim01.png -------------------------------------------------------------------------------- /patching-system/build/0/kodim19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/0/kodim19.png -------------------------------------------------------------------------------- /patching-system/build/1/kodim01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/1/kodim01.png -------------------------------------------------------------------------------- /patching-system/build/1/kodim19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/1/kodim19.png -------------------------------------------------------------------------------- /patching-system/build/300/kerp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/300/kerp.jpg -------------------------------------------------------------------------------- /patching-system/build/300/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/300/lena.png -------------------------------------------------------------------------------- /patching-system/build/300/kodim01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/300/kodim01.png -------------------------------------------------------------------------------- /patching-system/build/300/kodim19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/300/kodim19.png -------------------------------------------------------------------------------- /patching-system/server/patches/0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/server/patches/0.zip -------------------------------------------------------------------------------- /patching-system/build/1/arch0/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/1/arch0/lena.png -------------------------------------------------------------------------------- /patching-system/build/1/arch0/kodim01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/1/arch0/kodim01.png -------------------------------------------------------------------------------- /patching-system/build/1/arch0/kodim19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/patching-system/build/1/arch0/kodim19.png -------------------------------------------------------------------------------- /canvas_tiled_rendering/data/grits_master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas_tiled_rendering/data/grits_master.png -------------------------------------------------------------------------------- /canvas-faster-picking/tools/bin/textures/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/bin/textures/0.png -------------------------------------------------------------------------------- /canvas-faster-picking/tools/bin/textures/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/bin/textures/1.png -------------------------------------------------------------------------------- /canvas-faster-picking/tools/bin/textures/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/bin/textures/2.png -------------------------------------------------------------------------------- /canvas-faster-picking/tools/bin/textures/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/bin/textures/3.png -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/FreeImage.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/hullgen/FreeImage.h -------------------------------------------------------------------------------- /canvas-faster-picking/tools/bin/FreeImagePlus.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/bin/FreeImagePlus.dll -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/FreeImage.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/hullgen/FreeImage.lib -------------------------------------------------------------------------------- /stat_tracker/0.simple/gae_launch.bat: -------------------------------------------------------------------------------- 1 | python "C:\Program Files (x86)\Google\google_appengine\dev_appserver.py" . --skip_sdk_update_check --clear_datastore -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/GenSpriteHull.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/hullgen/GenSpriteHull.suo -------------------------------------------------------------------------------- /stat_tracker/1.client-gather/gae_launch.bat: -------------------------------------------------------------------------------- 1 | python "C:\Program Files (x86)\Google\google_appengine\dev_appserver.py" . --skip_sdk_update_check --clear_datastore -------------------------------------------------------------------------------- /canvas-faster-picking/tools/bin/builddata.bat: -------------------------------------------------------------------------------- 1 | hullbuild.exe textures/0.png 50 2 | hullbuild.exe textures/1.png 50 3 | hullbuild.exe textures/2.png 50 4 | hullbuild.exe textures/3.png 50 -------------------------------------------------------------------------------- /stat_tracker/0.simple/app.yaml: -------------------------------------------------------------------------------- 1 | application: statsgather 2 | version: 1 3 | runtime: python 4 | api_version: 1 5 | 6 | handlers: 7 | 8 | 9 | - url: .* 10 | script: main.py 11 | -------------------------------------------------------------------------------- /stat_tracker/2.server-gather/grits_gae_launch.bat: -------------------------------------------------------------------------------- 1 | cls 2 | 3 | python "C:\Program Files (x86)\Google\google_appengine\dev_appserver.py" . --skip_sdk_update_check --clear_datastore --backends -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/contrib/FreeImagePlus/FreeImagePlus.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/hullgen/contrib/FreeImagePlus/FreeImagePlus.dll -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/contrib/FreeImagePlus/FreeImagePlus.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/hullgen/contrib/FreeImagePlus/FreeImagePlus.h -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/contrib/FreeImagePlus/FreeImagePlus.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainroach/sandbox/HEAD/canvas-faster-picking/tools/hullgen/contrib/FreeImagePlus/FreeImagePlus.lib -------------------------------------------------------------------------------- /stat_tracker/1.client-gather/app.yaml: -------------------------------------------------------------------------------- 1 | application: statsgather 2 | version: 1 3 | runtime: python 4 | api_version: 1 5 | 6 | handlers: 7 | 8 | 9 | - url: .* 10 | script: main.py 11 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/Readme.md: -------------------------------------------------------------------------------- 1 | This is a test suite to show off various ways to render maps faster using HTML5 canvas. 2 | Please see the blog posts at http://mainroach.blogspot.com/2013/02/fast-html5-canvas-rendering-tiled-maps.html -------------------------------------------------------------------------------- /stat_tracker/2.server-gather/backends.yaml: -------------------------------------------------------------------------------- 1 | backends: 2 | 3 | # handle gathering, compressing, submitting of stats 4 | - name: statgather 5 | class: B1 6 | instances: 1 7 | options: dynamic, public 8 | start: ah_start_backend.py -------------------------------------------------------------------------------- /stat_tracker/2.server-gather/app.yaml: -------------------------------------------------------------------------------- 1 | application: stattest 2 | version: dev 3 | runtime: python27 4 | threadsafe: true 5 | api_version: 1 6 | 7 | inbound_services: 8 | - warmup 9 | 10 | handlers: 11 | 12 | - url: / 13 | static_files: index.html 14 | upload: index.html 15 | 16 | 17 | - url: /(.+\.(js)) 18 | static_files: \1 19 | upload: (.+\.(js)) 20 | mime_type: text/javascript 21 | 22 | 23 | - url: /.* 24 | script: main.app 25 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Canvas Tests


7 |

Forward rendering


8 |

Pre-Caching (GRITS)


9 |

Free-List-Caching


10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /chrome-event-trace/HOWTO.txt: -------------------------------------------------------------------------------- 1 | //myprogram.cpp 2 | #include "event_trace.h" 3 | #include "event_trace_plat.h" 4 | 5 | 6 | void somefunction() 7 | { 8 | TRACE_EVENT0("SUBSYSTEM","EventName") 9 | for(int i =0; i <100000); i++) 10 | { 11 | char* pDat = new char[50]; 12 | delete[] pDat; 13 | } 14 | } 15 | 16 | void main() 17 | { 18 | TRACE_EVENT_BEGIN(); //begin tracing (called at start of app) 19 | 20 | somefunction(); 21 | 22 | TRACE_EVENT_FINISH(); //end tracing (called at end of app) 23 | 24 | } 25 | 26 | //You'll need to define event_trace::OutputCallback, to determine how you want the JSON data to get handled: 27 | namespace event_trace 28 | { 29 | void OutputCallback (const char* pData) { fprintf(stdout,"PERF: %s\n",pData); } 30 | void BufferFullCallback() {TRACE_EVENT_FLUSH_LOG(); } 31 | }; -------------------------------------------------------------------------------- /stat_tracker/2.server-gather/ah_start_backend.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from google.appengine.api import apiproxy_stub_map 4 | from google.appengine.api import backends 5 | from google.appengine.api import runtime 6 | from google.appengine.api import users 7 | 8 | from google.appengine.ext import webapp 9 | 10 | from google.appengine.ext.webapp import template 11 | 12 | import cgi 13 | import datetime 14 | import logging 15 | import os 16 | import urllib 17 | 18 | 19 | my_name = '%s.%s (%s)' % (backends.get_backend(), backends.get_instance(), backends.get_url()) 20 | 21 | 22 | logging.info(my_name + ' is registering shutdown hook') 23 | 24 | 25 | def my_shutdown_hook(): 26 | logging.warning('shutdown hook called') 27 | apiproxy_stub_map.apiproxy.CancelApiCalls() 28 | # save_state() 29 | # May want to raise an exception 30 | 31 | # register our shutdown hook, which is not guaranteed to be called 32 | runtime.set_shutdown_hook(my_shutdown_hook) 33 | 34 | -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/GenSpriteHull.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GenSpriteHull", "GenSpriteHull.vcproj", "{58659F2D-6B75-464F-8C7B-BDEE5BBE6182}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {58659F2D-6B75-464F-8C7B-BDEE5BBE6182}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {58659F2D-6B75-464F-8C7B-BDEE5BBE6182}.Debug|Win32.Build.0 = Debug|Win32 14 | {58659F2D-6B75-464F-8C7B-BDEE5BBE6182}.Release|Win32.ActiveCfg = Release|Win32 15 | {58659F2D-6B75-464F-8C7B-BDEE5BBE6182}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/0_forward/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |

Canvas Test - Forward rendering


23 | W/S to move, A/D to rotate
24 | World is pretty large, you might run for a while...
25 |
26 | 27 | 28 | 33 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/2_refresh_tiling/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |

Canvas Test - Refrsh Free-List


22 | W/S to move, A/D to rotate
23 | This map uses the refresh tiling method, where we have a free-list of canvases tha get filled in as we request them for visibility.
24 | World is pretty large, you might run for a while...
25 |
26 | 27 | 28 | 33 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/1_grits_tiling/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 |

Canvas Test - Pre-Cached rendering (GRITS)


25 | W/S to move, A/D to rotate
26 | This map uses the tiling method from GRITS, where we pre-render the entire world into a series of off-screen canvases
27 | World is pretty large, you might run for a while...
28 |
29 | 30 | 31 | 36 | -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/imgHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | typedef unsigned char uint8; 8 | typedef signed char int8; 9 | typedef unsigned short uint16; 10 | typedef signed short int16; 11 | typedef unsigned int uint32; 12 | typedef uint32 uint; 13 | typedef signed int int32; 14 | typedef unsigned __int64 uint64; 15 | typedef signed __int64 int64; 16 | 17 | const uint8 UINT8_MIN = 0; 18 | const uint8 UINT8_MAX = 0xFFU; 19 | const uint16 UINT16_MIN = 0; 20 | const uint16 UINT16_MAX = 0xFFFFU; 21 | const uint32 UINT32_MIN = 0; 22 | const uint32 UINT32_MAX = 0xFFFFFFFFU; 23 | const uint64 UINT64_MIN = 0; 24 | const uint64 UINT64_MAX = 0xFFFFFFFFFFFFFFFFui64; 25 | 26 | const int8 INT8_MIN = -128; 27 | const int8 INT8_MAX = 127; 28 | const int16 INT16_MIN = -32768; 29 | const int16 INT16_MAX = 32767; 30 | const int32 INT32_MIN = (-2147483647 - 1); 31 | const int32 INT32_MAX = 2147483647; 32 | const int64 INT64_MIN = (-9223372036854775807i64 - 1); 33 | const int64 INT64_MAX = 9223372036854775807i64; 34 | 35 | #include "math.h" 36 | 37 | struct ImageData 38 | { 39 | std::string imgFileName; 40 | unsigned int uniqueID; 41 | unsigned int width; 42 | unsigned int height; 43 | char* pImgData; 44 | unsigned int imgSizeInBytes; 45 | unsigned char imgFormat; 46 | }; 47 | 48 | struct RGBAColor 49 | { 50 | unsigned char r; 51 | unsigned char g; 52 | unsigned char b; 53 | unsigned char a; 54 | }; 55 | struct RGBColor 56 | { 57 | unsigned char R; 58 | unsigned char G; 59 | unsigned char B; 60 | }; 61 | 62 | bool loadImageData(const char* pFilename, ImageData& id); 63 | bool saveImageData(const char* pFilename, ImageData& id); -------------------------------------------------------------------------------- /chrome-event-trace/event_trace.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "event_trace.h" 6 | 7 | namespace event_trace { 8 | 9 | void TraceEndOnScopeClose::Initialize(const unsigned char* category_enabled, 10 | const char* name) { 11 | data_.category_enabled = category_enabled; 12 | data_.name = name; 13 | p_data_ = &data_; 14 | } 15 | 16 | void TraceEndOnScopeClose::AddEventIfEnabled() { 17 | // Only called when p_data_ is non-null. 18 | if (*p_data_->category_enabled) { 19 | TRACE_EVENT_API_ADD_TRACE_EVENT( 20 | TRACE_EVENT_PHASE_END, 21 | p_data_->category_enabled, 22 | p_data_->name, kNoEventId, 23 | kZeroNumArgs, NULL, NULL, NULL, 24 | kNoThreshholdBeginId, kNoThresholdValue, TRACE_EVENT_FLAG_NONE); 25 | } 26 | } 27 | 28 | void TraceEndOnScopeCloseThreshold::Initialize( 29 | const unsigned char* category_enabled, 30 | const char* name, 31 | int threshold_begin_id, 32 | long long threshold) { 33 | data_.category_enabled = category_enabled; 34 | data_.name = name; 35 | data_.threshold_begin_id = threshold_begin_id; 36 | data_.threshold = threshold; 37 | p_data_ = &data_; 38 | } 39 | 40 | void TraceEndOnScopeCloseThreshold::AddEventIfEnabled() { 41 | // Only called when p_data_ is non-null. 42 | if (*p_data_->category_enabled) { 43 | TRACE_EVENT_API_ADD_TRACE_EVENT( 44 | TRACE_EVENT_PHASE_END, 45 | p_data_->category_enabled, 46 | p_data_->name, kNoEventId, 47 | kZeroNumArgs, NULL, NULL, NULL, 48 | p_data_->threshold_begin_id, p_data_->threshold, 49 | TRACE_EVENT_FLAG_NONE); 50 | } 51 | } 52 | 53 | } // namespace event_trace 54 | -------------------------------------------------------------------------------- /needle.js/tests/perf_base.html: -------------------------------------------------------------------------------- 1 | 14 | 15 |
This test will time base-performance of the algorithm. In a seperate file to ensure manual reloads to cause lingering GC overhead...

16 | 17 |
working...
18 | 19 | 20 | 21 | 22 | 75 | 76 | -------------------------------------------------------------------------------- /stat_tracker/2.server-gather/stats_backend.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement #for blobstore 2 | from google.appengine.api import files #for blobstore 3 | from google.appengine.ext import blobstore #for blobstore 4 | from google.appengine.api import backends 5 | from google.appengine.api import users 6 | 7 | import copy 8 | import logging 9 | import pprint as pp 10 | import random 11 | import sys 12 | import json 13 | 14 | def tojson(python_object): 15 | """Helper function to output and optionally pretty print JSON.""" 16 | return json.JSONEncoder().encode(python_object) 17 | 18 | def e(msg): 19 | """Convient method to raise an exception.""" 20 | raise Exception(repr(msg)) 21 | 22 | 23 | def w(msg): 24 | """Log a warning message.""" 25 | logging.warning('##### %s' % repr(msg)) 26 | 27 | 28 | class StatsGather: 29 | 30 | buffer0="" 31 | curBufferIdx=0 32 | curBuffer=None 33 | runningByteLen=0 34 | bufferSize = 1024*5 35 | def __init__(self): 36 | self.buffer0 = "" 37 | self.curBuffer = self.buffer0 38 | self.runningByteLen = 0 39 | 40 | 41 | def addGameEvent(self,eventType, eventName, eventMeta, dob): 42 | v = { 43 | "eventType":str(eventType), 44 | "eventName":str(eventName), 45 | "eventMeta":str(eventMeta), 46 | "dob":str(dob) 47 | } 48 | enc = tojson(v) 49 | dlen = len(enc) 50 | if(dlen + self.runningByteLen >= self.bufferSize): 51 | self.forceFlush() 52 | 53 | self.runningByteLen = self.runningByteLen + len(enc) 54 | if(self.runningByteLen == 0): 55 | self.buffer0 = str(v) 56 | else: 57 | self.buffer0 = self.buffer0 + "," + str(v) 58 | 59 | # logging.info("buffer-" + self.buffer0) 60 | 61 | def forceFlush(self): 62 | 63 | self.flushBuffer(self.buffer0 + " ") 64 | self.buffer0 = "" 65 | self.runningByteLen = 0; 66 | 67 | def flushBuffer(self,batchData): 68 | #logging.info("buffer-" + batchData) 69 | 70 | if(len(batchData)==0): 71 | return 72 | #flush the string to the DB 73 | file_name = files.blobstore.create(mime_type='application/octet-stream') 74 | with files.open(file_name, 'a') as f: 75 | f.write(batchData) 76 | files.finalize(file_name)# Finalize the file. Do this before attempting to read it. 77 | blob_key = files.blobstore.get_blob_key(file_name) 78 | 79 | logging.info("BK:FLUSHED") 80 | 81 | return blob_key 82 | -------------------------------------------------------------------------------- /needle.js/tests/depth_test.html: -------------------------------------------------------------------------------- 1 | 14 | 15 |
16 | This test will see how deep in a callstack needle can go before breaking the universe.
NOTE take this below data, copy-Paste it into a "trace.json" file on disk, and then load it into chrome's "about://tracing" page

17 |
working...
18 | 19 | 20 | 21 | 22 | 90 | 91 | -------------------------------------------------------------------------------- /patching-system/client/client.py: -------------------------------------------------------------------------------- 1 | 2 | import urllib 3 | import xml.dom.minidom as minidom 4 | import subprocess 5 | import os.path 6 | import json 7 | import datetime 8 | import urllib2 9 | import sys 10 | from urlparse import urljoin 11 | import zipfile 12 | import os.path, time 13 | from os import listdir 14 | from os.path import isfile, join 15 | 16 | client_buildNum = 1 17 | client_region = 'usa' 18 | localDataPath = "./data/" 19 | 20 | #this function will update our local data to match the server version 21 | 22 | #grab server version 23 | url="http://localhost:8080/" 24 | fileList = url + "filelist.json" 25 | f = urllib.urlopen(fileList) 26 | server_manifest_data = f.read() 27 | server_manifest = json.loads(server_manifest_data) 28 | 29 | #sort our builds by number 30 | builds = server_manifest['builds'] 31 | builds.sort(key=lambda bld: bld['buildnum']) 32 | 33 | targets=[] 34 | for build in builds: 35 | if build['buildnum'] > client_buildNum: 36 | targets.append(build); 37 | 38 | if len(targets) == 0: sys.exit() 39 | 40 | cdnPath = url + "patches/" 41 | if not os.path.exists(localDataPath): os.makedirs(localDataPath) 42 | for build in targets: 43 | #files to add 44 | for file in build["add-files"]: 45 | fileurl = cdnPath + file 46 | localurl = localDataPath + file 47 | print "fetching:" + fileurl + " to " + localurl 48 | 49 | #write this file data to disk 50 | #NOTE in python, if this file already exists, then the following will over-write it 51 | f = urllib.urlopen(fileurl) 52 | fl = open(localurl,'wb') 53 | fl.write(f.read()); 54 | fl.close(); 55 | #files to remove 56 | #files to patch 57 | #update our build number 58 | client_buildNum = build['buildnum'] 59 | 60 | #this function will initalize our filesystem by loading archives 61 | #it does things the slow, boring way just to show off the concepts 62 | 63 | gArchives=[] 64 | 65 | for f in listdir(localDataPath): 66 | fname = join(localDataPath,f) 67 | 68 | if not isfile(fname): continue 69 | obj = {"fname":fname,"time":time.ctime(os.path.getmtime(fname)) } 70 | gArchives.append(obj) 71 | 72 | #sort our archives based upon time 73 | gArchives.sort(key=lambda app: app["time"],reverse=True ) 74 | 75 | 76 | 77 | #FETCH SOME DATA 78 | fname = "arch0/kodim01.png" 79 | for a in gArchives: 80 | zf = zipfile.ZipFile(a['fname'], 'r') 81 | try: 82 | info = zf.getinfo(fname) 83 | except KeyError: 84 | print fname + " not found in " + a['fname'] 85 | continue; 86 | else: 87 | print '%s is %d bytes in %s' % (info.filename, info.file_size, a['fname']) 88 | break; 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /stat_tracker/1.client-gather/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 67 | 68 | 69 | 70 | 71 | 72 |

Stats gathering test to GAE

73 | It's all about the pricing. Can we do 40MM stats/day for less than $100?

74 | Generate Events :
75 | 144890b per write is $0.00001/mo @($0.13 / G / month)
76 |
Fetch Events Results:
77 | (view console)
78 | 79 |
80 | 81 |
82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /needle.js/Readme.md: -------------------------------------------------------------------------------- 1 | Needle.js 2 | ========= 3 | 4 | Needle.js is a minimalistic javascript inline-profiling library which aims to add the least amount of memory and runtime overhead possible. Right now we have a _~0.0001ms - ~0.0004ms_ overhead (tested on windows) per event; (e.g 10,000 begin/end blocks adds about ~2.6ms - 7ms overhead to your frame.) 5 | 6 | ## Why Needle.js? 7 | 8 | 9 | The HTML5 implimentation for console.begin/endTime add too much overhead per sample (~0.02ms), and are not usable for fine-grain sampling. Game developers often need to check the performance differences between two inner-loop algorithms, and need more samples / frame. 10 | 11 | ## Why is Needle.js fast? 12 | 13 | 14 | Needle.js focuses on being fast-first, not being polyfilled or functional. It's built to give you timings in your code. 15 | 16 | 1. Reduces memory-churn by using a dynamic array of bucketed samples; allowing you to pre-allocate, and also add samples as you run. 17 | 18 | 2. Takes advantage of the fact that static strings should be hashed in JS already. So doing begin("foo") will just pass a reference around. That being said begin("foo" + str(entity.ID)) will add a NEW string to the JS heap, EACH call; So try to stay using static strings. 19 | 20 | 3. Utilizes typed arrays and direct memory assignment rather than new-object creation. 21 | 22 | 23 | 24 | ## USAGE 25 | 26 | To Enable/Disable Needle, call the `needle.enable()` and `needle.disable()` functions. 27 | NOTE Needle is DISABLED by default. 28 | 29 | Call `Needle.init` with the number of up-front samples you want to allocate for: 30 | 31 | `Needle.init(10000,false);` 32 | 33 | Note that 2nd parameter is a boolean value representing if needle should run in high-precision mode or not. 34 | 35 | * The Low precision mode will return timings a the 1ms resolution. 36 | 37 | * The High precision mode will return timings at < 1ms resolution, but will run almost 3x slower as a result. 38 | 39 | 40 | 41 | 42 | Then you need to add begin/end scopes around blocks of code you are interested in timing: 43 | 44 | ` 45 | Needle.begin("start of scope"); 46 | 47 | //....do some stuff 48 | 49 | Needle.end() 50 | ` 51 | 52 | 53 | Also fine to nest Needle scopes: 54 | 55 | ` 56 | Needle.begin("start of scope"); 57 | 58 | Needle.begin("MORE scope"); 59 | 60 | //....do some stuff 61 | 62 | Needle.end() 63 | 64 | Needle.end() 65 | ` 66 | 67 | 68 | To clean/reset Needle simply call: 69 | 70 | `needle.init(..) ` 71 | 72 | again to clean and resue it immediatly. 73 | 74 | 75 | 76 | ## DISCLAIMER 77 | 78 | *I've only tested this in CHROME 26 beta; I make no warranties that it works in other browsers / versions 79 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/mrdoob-stats.js: -------------------------------------------------------------------------------- 1 | // stats.js r9 - http://github.com/mrdoob/stats.js 2 | var Stats=function(){var h,a,r=0,s=0,i=Date.now(),u=i,t=i,l=0,n=1E3,o=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,p=1E3,q=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();r=(r+1)%2;0==r?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= 3 | "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= 4 | "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);74>f.children.length;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= 5 | "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);74>g.children.length;)a=document.createElement("span"), 6 | a.style.width="1px",a.style.height=30*Math.random()+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{getDomElement:function(){return h},getFps:function(){return l},getFpsMin:function(){return n},getFpsMax:function(){return o},getMs:function(){return m},getMsMin:function(){return p},getMsMax:function(){return q},update:function(){i=Date.now();m=i-u;p=Math.min(p,m);q=Math.max(q,m);k.textContent=m+" MS ("+p+"-"+q+")";var a=Math.min(30, 7 | 30-30*(m/200));g.appendChild(g.firstChild).style.height=a+"px";u=i;s++;if(i>t+1E3)l=Math.round(1E3*s/(i-t)),n=Math.min(n,l),o=Math.max(o,l),j.textContent=l+" FPS ("+n+"-"+o+")",a=Math.min(30,30-30*(l/100)),f.appendChild(f.firstChild).style.height=a+"px",t=i,s=0}}}; -------------------------------------------------------------------------------- /stat_tracker/0.simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 82 | 83 | 84 | 85 | 86 | 87 |

Simple Stats gathering test to GAE

88 | It's all about the pricing. Can we do 40MM stats/day for less than $100?

89 | Generate Events :
90 |
91 | $0.05/day @ ($0.10/100k write ops)
92 |
Fetch Events Results:
93 | (view console)
94 | 95 |
96 | 97 |
98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /stat_tracker/1.client-gather/main.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement #for blobstore 2 | from google.appengine.api import files #for blobstore 3 | from google.appengine.ext import blobstore #for blobstore 4 | import os; 5 | from google.appengine.api import users 6 | from google.appengine.ext import webapp 7 | from google.appengine.ext.webapp import template 8 | from google.appengine.ext.webapp.util import run_wsgi_app 9 | from google.appengine.ext.db import stats#https://developers.google.com/appengine/docs/python/datastore/stats 10 | 11 | import os; 12 | import cgi 13 | import datetime 14 | import urllib 15 | import json 16 | import logging 17 | import wsgiref.handlers 18 | from google.appengine.ext.webapp import util 19 | from google.appengine.ext import db 20 | import wsgiref.handlers 21 | import random 22 | from types import * 23 | 24 | def tojson(python_object): 25 | """Helper function to output and optionally pretty print JSON.""" 26 | return json.JSONEncoder().encode(python_object) 27 | 28 | def fromjson(msg): 29 | """Helper function to ingest JSON.""" 30 | try: 31 | return json.loads(msg) 32 | except Exception, e: 33 | raise Exception('Unable to parse as JSON: %s' % msg) 34 | 35 | class RootHandler(webapp.RequestHandler): 36 | def get(self): 37 | path = os.path.join(os.path.dirname(__file__), 'index.html') 38 | self.response.out.write(template.render(path, {})) 39 | 40 | 41 | #----------------------------------------------------- 42 | 43 | 44 | def addGameBatchEvent(batchData): 45 | # Create the file 46 | file_name = files.blobstore.create(mime_type='application/octet-stream') 47 | 48 | # Open the file and write to it 49 | with files.open(file_name, 'a') as f: 50 | f.write(batchData) 51 | files.finalize(file_name)# Finalize the file. Do this before attempting to read it. 52 | 53 | # Get the file's blob key 54 | blob_key = files.blobstore.get_blob_key(file_name) 55 | 56 | return blob_key 57 | 58 | 59 | #----------------------------------------------------- 60 | class StatsHandler(webapp.RequestHandler): 61 | def post(self,fcn): 62 | if(fcn == "addbatch"): 63 | ip = self.request.remote_addr 64 | metadata = self.request.body 65 | key = addGameBatchEvent(metadata) 66 | self.response.out.write(key) 67 | def get(self,fcn): 68 | if(fcn == "blobs"): 69 | # self.postBackendFlush() 70 | gqlQuery = blobstore.BlobInfo.gql("ORDER BY creation DESC") 71 | blobs = gqlQuery.fetch(10) 72 | 73 | outStr = "[" 74 | for blob in blobs: 75 | blob_reader = blobstore.BlobReader(blob.key()) 76 | value = blob_reader.read() 77 | #logging.info("VVVVVVV" + value) 78 | outStr = outStr + value 79 | outStr = outStr + "]" 80 | 81 | #pass back to the client for display 82 | self.response.headers['Content-Type'] = 'application/json' 83 | self.response.out.write(outStr) 84 | 85 | 86 | 87 | application = webapp.WSGIApplication( 88 | [('/', RootHandler), 89 | ('/s/(.*)', StatsHandler)], 90 | 91 | debug=True) 92 | 93 | def main(): 94 | run_wsgi_app(application) 95 | 96 | if __name__ == '__main__': 97 | main() 98 | -------------------------------------------------------------------------------- /chrome-event-trace/win_test/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | #include "../event_trace.h" 11 | #include "../event_trace_plat.h" 12 | 13 | FILE* logfil = NULL; 14 | 15 | namespace event_trace 16 | { 17 | 18 | void OutputCallback (const char* pData) { printf(pData); fwrite(pData,strlen(pData),1,logfil); } 19 | void BufferFullCallback() {TRACE_EVENT_FLUSH_LOG(); } 20 | }; 21 | 22 | #define BASIC_TEST 23 | #define THREADED_TEST 24 | 25 | #ifdef THREADED_TEST 26 | void workFunction(void* pData) 27 | { 28 | 29 | { 30 | 31 | TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); 32 | 33 | for(int i =0; i < 1000000; i++) 34 | { 35 | const int c = 20+ 30 + rand()%500 - GetCurrentThreadId(); 36 | char* pdat = new char[1]; 37 | delete[] pdat; 38 | } 39 | 40 | } 41 | 42 | TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "EVENT HIT THE FAN"); 43 | { 44 | TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly222"); 45 | for(int i =0; i < 1000000; i++) 46 | { 47 | const int c = 20+ 30 + rand()%500 - GetCurrentThreadId(); 48 | char* pdat = new char[1]; 49 | delete[] pdat; 50 | 51 | } 52 | } 53 | 54 | 55 | { 56 | TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly333"); 57 | for(int i =0; i < 1000; i++) 58 | { 59 | TRACE_EVENT2("MY_SUBSYSTEM", "ILIKECHEESE","objName","Falcore","HPVal","88"); 60 | const int c = 20+ 30 + rand()%500 - GetCurrentThreadId(); 61 | char* pdat = new char[1]; 62 | delete[] pdat; 63 | 64 | } 65 | } 66 | 67 | } 68 | 69 | void workFunction2(void* pData) 70 | { 71 | 72 | { 73 | TRACE_EVENT0("MY_SUBSYSTEM", "22doSomethingCostly"); 74 | for(int i =0; i < 10000; i++) 75 | { 76 | const int c = 20+ 30 + rand()%500 - GetCurrentThreadId(); 77 | char* pdat = new char[1]; 78 | delete[] pdat; 79 | 80 | } 81 | } 82 | 83 | TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "EVENT HIT THE FAN 2"); 84 | { 85 | TRACE_EVENT0("MY_SUBSYSTEM", "22doSomethingCostly222"); 86 | for(int i =0; i < 10000; i++) 87 | { 88 | const int c = 20+ 30 + rand()%500 - GetCurrentThreadId(); 89 | char* pdat = new char[1]; 90 | delete[] pdat; 91 | 92 | } 93 | } 94 | 95 | 96 | { 97 | TRACE_EVENT0("MY_SUBSYSTEM", "22doSomethingCostly333"); 98 | for(int i =0; i < 10000; i++) 99 | { 100 | const int c = 20+ 30 + rand()%500 - GetCurrentThreadId(); 101 | char* pdat = new char[1]; 102 | delete[] pdat; 103 | 104 | } 105 | } 106 | 107 | } 108 | 109 | 110 | #endif 111 | int main() 112 | { 113 | logfil = fopen("out.json","wb"); 114 | 115 | 116 | TRACE_EVENT_BEGIN(); 117 | 118 | 119 | 120 | #ifdef BASIC_TEST 121 | workFunction(0); 122 | #endif 123 | 124 | 125 | #ifdef THREADED_TEST 126 | uintptr_t threadHandle = _beginthread(workFunction2, 0, 0); 127 | workFunction(0); 128 | #endif 129 | 130 | 131 | TRACE_EVENT_FINISH(); 132 | fclose(logfil); 133 | logfil = 0; 134 | 135 | } -------------------------------------------------------------------------------- /stat_tracker/2.server-gather/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 83 | 84 | 85 | 86 | 87 | 88 |

Stats gathering test to GAE

89 | It's all about the pricing. Can we do 40MM stats/day for less than $100?

90 | Generate Events :
91 | Each stat pushed up individually; GAE has running back-end that collects and pushes a blob. $xx day @ ($0.16/hr + $0.13 /G/month data)
92 |
93 | 94 | 95 |
Fetch Events Results:
96 | (view console)
97 | 98 |
99 | 100 |
101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/data/map.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | eJzt0zERACAMALFiBf8iUfATE1yGSMiamXVhw8dubvjB7/yA5gc0P6D5Ac0PaH5A8wOaH9D8gOYHND+g+QHND2h+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC84QAIaKCt 9 | 10 | 11 | 12 | 13 | eJzt20FuI0UYQOHZACcBTgKcC1gguAUgIeAWwIJr0SNkyYpc/couT14K3pN6MUm+6j+OnW7P1Hz/7t27vx88fjiO7/P5jT3168TXjPoln9/cU/Z8H9J/fRzfHMe3E56+dtXf+vxbf/zu9be+x7PH5S3MT9nzfUj/43H8dBw/T3j6Wnp+k7/1+dnX1+hzFz/72n75dWfnpz+/9O+79T2ePS5v4flD2fPR75+V8/9xHH8ex18Tnr6Wnt/kb31+9vU1+tzF02tztM7Z+enPL/37bn2PZ49Lr4/7/OzPefb899xfUfT8fqTZ19focxdPr83ROmfnpz9f+2dcvx7JfH18dBwfH8cnsP4z/fXP4Bnnv+f+6pZ/7e9/V3/rcb7469fE2fXLmp8arf/pcXx2HJ/D+iM/8zvlzK+e/72/5/7qmee//t5n/cvH6/r8j7z/mPnYrKfzXz/Ol6+7zH/9mji7fr3sGT//GU+N1v/iOL48jq9g/ZGfuVc686vnN/319z7rXz5e1+d/5P3HzMdmPZ3/lrnM/+j7j9f6+VEf6v5v5p74Ldx/Puvvd68bfe9n99/Pfv8x87FZT+enOS/9l95/zK7/Gp6u7/e6W/7sejdz/pnX16PPj9nn5729hn/0/cezzk+esueb8bPX91l3y5/97ps5/8z95NnzY+XfP8iPOvv79UfeP94yj77/mKnXx789+vtz5f35veefuZ88e36s/PsH+Ut0/Zp5zzE6/2iG/v0j/wy/8v6D/CW6v5l5zzE6/+wMZ/7een3kn+nf4v2N7anfjuO7B4/f8/nNPWXvv8/nTU/Z17d83vSUPV8+b3rKni+fNz1lz5fPm56y58vnTU+N1t/p/x/k8496arT+a+2/z+dNT43W3/n/X+Tzb/3/f+TzO3jKni+fNz1lz5fPm56y58vnTU/Z8+Xzpqfs+fJ501P2/vt83vSUvf8+nzc9ZV/f8nnTU/Z8+bzpKXu+fN70lD1fPm96yp4vnzc9NVp/l/37+fyKp0br77J/P59f8dRo/V327+fzK56y7//yedNT9nz5vOkpe7583vSUPV8+b3rKni+fNz1lz5fPm56y99/n86an7P33+bzpKfv6ls+bnrLny+dNT9nz5fOmp+z58nnTU/Z8+bzpqdH6u+zfz+dXPDVaf5f9+/n8iqdG6++yfz+fX/GUff+Xz5uesufL501P2fPl86an7PnyedNT9nz5vOkpe7583vSUvf8+nzc9Ze+/z+dNT9nXt3ze9JQ9Xz5vesqeL583PWXPl8+bnrLny+dNT43W32X/fj6/4qnR+rvs38/nVzw1Wn+X/fv5/Iqn7Pu/fN70lD1fPm96yp4vnzc9Zc+Xz5uesufL501P2fPl86an7P33+bzpKXv/fT5vesq+vuXzpqfs+fJ501P2fPm86Sl7vnze9JQ9Xz5vemq0/i779/P5FU+N1t9l/34+v+Kp0fq77N/P51c8Zd//5fOmp+z58nnTU/Z8+bzpKXu+fN70lD1fPm96yp4vnzc9Ze+/z+dNT9n77/N501P29S2fNz1lz5fPm56y58vnTU/Z8+Xzpqfs+fJ501Oj9XfZv5/Pr3hqtP4u+/fz+RVPjdbfZf9+Pr/iKfv+L583PWXPl8+bnrLny+dNT9nz5fOmp+z58nnTU/Z8+bzpKXv/fT5vesref5/Pm56yr2/5vOkpe7583vSUPV8+b3rKni+fNz1lz5fPm54arb/L/v18fsVTo/V32b+fz694arT+Lvv38/kVT9n3f/m86Sl7vnze9JQ9Xz5vesqeL583PWXPl8+bnrLny+dNT9n77/N501P2/vt83vSUfX3L501P2fPl86an7PnyedNT9nz5vOkpe7583vTUaP1d9u/n8yueGq2/y/79fH7FU6P1d9m/n8+veMq+/8vnTU/Z8+Xzpqfs+fJ501P2fPm86Sl7vnze9JQ9Xz5vesref5/Pm56y99/n86an7OtbPm96yp4vnzc9Zc+Xz5uesufL501P2fPl86anRuvvsn8/n1/x1Gj9Xfbv5/Mrnhqtv8v+/Xx+xVP2/V8+b3rKni+fNz1lz5fPm56y58vnTU/Z8+Xzpqfs+fJ501P2/vt83vSUvf8+nzc9ZV/f8nnTU/Z8+bzpKXu+fN70lD1fPm96yp4vnzc9NVp/l/37+fyKp0br77J/P59f8dRo/V327+fzK56y7//yedNT9nz5vOkpe7583vSUPV8+b3rKni+fNz1lz5fPm56y99/n86an7P33+bzpKfv6ls+bnrLny+dNT9nz5fOmp+z58nnTU/Z8+bzpqdH6u+zfz+dXPDVaf5f9+/n8iqdG6++yfz+fX/GUff+Xz5uesufL501P2fPl86an7PnyedNT9nz5vOkpe7583vSUvf8+nzd9VVVVVVVVVVVVVVXV/61/AAFIpb4= 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /needle.js/tests/perf_console_time.html: -------------------------------------------------------------------------------- 1 | 14 | 15 |
This test will time Console.time/timeend per-event overhead. In a seperate file to ensure manual reloads to cause lingering GC overhead...

16 | 17 |
working...
18 | 19 | 20 | 21 | 116 | 117 | -------------------------------------------------------------------------------- /stat_tracker/0.simple/main.py: -------------------------------------------------------------------------------- 1 | 2 | import os; 3 | from google.appengine.api import users 4 | from google.appengine.ext import webapp 5 | from google.appengine.ext.webapp import template 6 | from google.appengine.ext.webapp.util import run_wsgi_app 7 | from google.appengine.ext import ndb 8 | from google.appengine.ext import db 9 | from google.appengine.ext.db import stats#https://developers.google.com/appengine/docs/python/datastore/stats 10 | 11 | import os; 12 | import cgi 13 | import datetime 14 | import urllib 15 | import json 16 | import logging 17 | import wsgiref.handlers 18 | from google.appengine.ext.webapp import util 19 | from google.appengine.ext import db 20 | import wsgiref.handlers 21 | import random 22 | from types import * 23 | 24 | def tojson(python_object): 25 | """Helper function to output and optionally pretty print JSON.""" 26 | return json.JSONEncoder().encode(python_object) 27 | 28 | def fromjson(msg): 29 | """Helper function to ingest JSON.""" 30 | try: 31 | return json.loads(msg) 32 | except Exception, e: 33 | raise Exception('Unable to parse as JSON: %s' % msg) 34 | 35 | class RootHandler(webapp.RequestHandler): 36 | def get(self): 37 | path = os.path.join(os.path.dirname(__file__), 'index.html') 38 | self.response.out.write(template.render(path, {})) 39 | 40 | #----------------------------------------------------- 41 | class GameEvent(ndb.Model): 42 | eventType = ndb.StringProperty(indexed=False) 43 | eventName = ndb.StringProperty(indexed=False) 44 | eventMeta = ndb.StringProperty(indexed=False) 45 | createDate = ndb.DateTimeProperty(indexed=False) 46 | 47 | def tojson(self): 48 | v = { 49 | 'eventType':str(self.eventType), 50 | 'eventName':str(self.eventName), 51 | 'eventMeta':str(self.eventMeta), 52 | 'dob':str(self.createDate) 53 | } 54 | return tojson(v) 55 | 56 | #----------------------------------------------------- 57 | def addGameEvent(eventType, eventName, eventMeta): 58 | usr = GameEvent() 59 | usr.eventType = eventType 60 | usr.eventName = eventName 61 | usr.eventMeta = eventMeta 62 | usr.put() 63 | return usr 64 | 65 | #----------------------------------------------------- 66 | def getAllEvents(): 67 | zones = ndb.gql("SELECT * FROM GameEvent") 68 | return zones 69 | 70 | 71 | #----------------------------------------------------- 72 | class StatsHandler(webapp.RequestHandler): 73 | def post(self,fcn): 74 | if(fcn == "add"): 75 | type = self.request.get('type',"unknown") 76 | name = self.request.get('name',"unknown") 77 | #logging.info( "====BODY: " +self.request.body) 78 | #params = fromjson(self.request.body) #CLM this has a problem. the incoming data isn't formatted nicely due to it's header being x-www-form-urlencoded 79 | ip = self.request.remote_addr 80 | metadata = self.request.body 81 | addGameEvent(type,name,metadata) 82 | def get(self,fcn): 83 | if(fcn == "events"): 84 | for evt in getAllEvents(): 85 | self.response.out.write(evt.tojson()) 86 | 87 | 88 | 89 | 90 | application = webapp.WSGIApplication( 91 | [('/', RootHandler), 92 | ('/s/(.*)', StatsHandler)], 93 | 94 | debug=True) 95 | 96 | def main(): 97 | run_wsgi_app(application) 98 | 99 | if __name__ == '__main__': 100 | main() 101 | -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/imgHelper.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "imgHelper.h" 3 | 4 | //devil 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | #include "./contrib/FreeImagePlus/FreeImagePlus.h" 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | 13 | #pragma comment(lib, "./contrib/FreeImagePlus/freeimageplus.lib") 14 | 15 | 16 | static bool readFileIntoMemory(const char* pFilename, unsigned int& dataSize, char** pData) 17 | { 18 | //read the input file list into memory 19 | FILE* f = fopen(pFilename, "rb"); 20 | 21 | if(!f) 22 | return false; 23 | 24 | 25 | fseek( f, 0L, SEEK_END ); 26 | dataSize = ftell( f ); 27 | rewind ( f ); 28 | 29 | *pData = new char[dataSize + 1]; 30 | 31 | const unsigned int v = (unsigned int)fread(*pData, dataSize, 1, f); 32 | assert(v == 1); 33 | if(v != 1) 34 | { 35 | delete[] *pData; 36 | return false; 37 | } 38 | 39 | (*pData) [dataSize] = '\0'; //string must be null terminated for RAPIDXML to work.. 40 | fclose( f ); 41 | 42 | return true; 43 | } 44 | 45 | //---------------------------------------------- 46 | bool loadImageData(const char* pFilename, ImageData& id) 47 | { 48 | 49 | 50 | id.imgFileName = pFilename; 51 | { 52 | 53 | fipImage src_image; 54 | 55 | if (!src_image.load(pFilename, 0)) 56 | return false; 57 | 58 | if (!src_image.convertTo32Bits()) 59 | return false; 60 | 61 | if (src_image.getBitsPerPixel() != 32) 62 | return false; 63 | 64 | id.width = src_image.getWidth(); 65 | id.height = src_image.getHeight(); 66 | 67 | 68 | id.imgSizeInBytes = id.width * id.height * 4; 69 | id.pImgData = new char[id.imgSizeInBytes]; 70 | 71 | char* pDest = id.pImgData; 72 | for (unsigned int y = 0; y < id.height; y++) 73 | { 74 | const unsigned char* pSrc = src_image.getScanLine((WORD)(id.height - 1 - y)); 75 | RGBAColor* pD = (RGBAColor*)pDest; 76 | 77 | for (uint x = id.width; x; x--) 78 | { 79 | RGBAColor c; 80 | c.r = pSrc[FI_RGBA_RED]; 81 | c.g = pSrc[FI_RGBA_GREEN]; 82 | c.b = pSrc[FI_RGBA_BLUE]; 83 | c.a = pSrc[FI_RGBA_ALPHA]; 84 | 85 | pSrc += 4; 86 | *pD++ = c; 87 | } 88 | 89 | 90 | pDest += (id.width*4); 91 | } 92 | 93 | 94 | 95 | } 96 | 97 | return true; 98 | } 99 | 100 | 101 | bool saveImageData(const char* pFilename, ImageData& id) 102 | { 103 | fipImage dst_image(FIT_BITMAP, (WORD)id.width, (WORD)id.height, 32); 104 | 105 | for (uint y = 0; y < id.height; y++) 106 | { 107 | int idx = y* id.width * 4; 108 | for (uint x = 0; x < id.width; x++, idx+=4) 109 | { 110 | RGBAColor c; 111 | 112 | RGBQUAD quad; 113 | quad.rgbRed = id.pImgData[idx +0]; 114 | quad.rgbGreen = id.pImgData[idx +1]; 115 | quad.rgbBlue = id.pImgData[idx +2]; 116 | quad.rgbReserved = id.pImgData[idx +3]; 117 | 118 | dst_image.setPixelColor(x, id.height - 1 - y, &quad); 119 | } 120 | } 121 | 122 | if (!dst_image.save(pFilename, 0)) 123 | return false; 124 | 125 | return true; 126 | } 127 | -------------------------------------------------------------------------------- /needle.js/tests/perf_needle_disabled.html: -------------------------------------------------------------------------------- 1 | 14 | 15 |
This test will time Needle.js per-event overhead.

16 | 17 |
working...
18 | 19 | 20 | 21 | 22 | 122 | 123 | -------------------------------------------------------------------------------- /needle.js/tests/perf_needle_coarse.html: -------------------------------------------------------------------------------- 1 | 14 | 15 |
This test will time Needle.js per-event overhead in COARSE mode. In a seperate file to ensure manual reloads to cause lingering GC overhead...

16 | 17 |
working...
18 | 19 | 20 | 21 | 22 | 125 | 126 | -------------------------------------------------------------------------------- /needle.js/tests/perf_needle_fine.html: -------------------------------------------------------------------------------- 1 | 14 | 15 |
This test will time Needle.js per-event overhead in FINE mode. In a seperate file to ensure manual reloads to cause lingering GC overhead...

16 | 17 |
working...
18 | 19 | 20 | 21 | 22 | 125 | 126 | -------------------------------------------------------------------------------- /chrome-event-trace/event_trace_plat.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file defines platform specific items that are required by event_trace 3 | */ 4 | #ifndef EVENT_TRACE_PLAT_H 5 | #define EVENT_TRACE_PLAT_H 6 | 7 | 8 | #include 9 | #ifdef OS_WIN 10 | #include 11 | #elif defined(__GNUC__) 12 | #include 13 | #include 14 | #endif 15 | 16 | namespace event_trace 17 | { 18 | 19 | 20 | 21 | //////////////////////////////// 22 | //TYPEDEFS 23 | //////////////////////////////// 24 | typedef char int8; 25 | typedef unsigned char uint8; 26 | typedef short int16; 27 | typedef unsigned short uint16; 28 | typedef int int32; 29 | typedef unsigned int uint32; 30 | 31 | 32 | #ifdef OS_WIN 33 | 34 | typedef __int64 int64; 35 | typedef unsigned __int64 uint64; 36 | #define _tlsVal __declspec(thread) 37 | 38 | #elif defined(__GNUC__) 39 | 40 | typedef long long int64; 41 | typedef unsigned long long uint64; 42 | #define _tlsVal __thread 43 | 44 | #endif 45 | 46 | 47 | //////////////////////////////// 48 | //TIMERS 49 | //////////////////////////////// 50 | typedef unsigned long long timer_ticks; 51 | typedef timer_ticks TimeTicks; 52 | #if defined(OS_WIN) 53 | inline void query_counter(timer_ticks *pTicks){ 54 | QueryPerformanceCounter(reinterpret_cast(pTicks)); 55 | } 56 | 57 | inline void query_counter_frequency(timer_ticks *pTicks){ 58 | QueryPerformanceFrequency(reinterpret_cast(pTicks)); 59 | } 60 | #elif defined(__GNUC__) 61 | #include 62 | inline void query_counter(timer_ticks *pTicks){ 63 | struct timeval cur_time; 64 | gettimeofday(&cur_time, NULL); 65 | *pTicks = static_cast(cur_time.tv_sec)*1000000ULL + static_cast(cur_time.tv_usec); 66 | } 67 | inline void query_counter_frequency(timer_ticks *pTicks){ 68 | *pTicks = 1000000; 69 | } 70 | #endif 71 | 72 | 73 | //////////////////////////////// 74 | //LOCKING 75 | //////////////////////////////// 76 | class Lock 77 | { 78 | 79 | #if defined(OS_WIN) 80 | public: 81 | Lock(){InitializeCriticalSectionAndSpinCount(&mCrit, 0); }; 82 | ~Lock(){DeleteCriticalSection(&mCrit); }; 83 | void Aquire(){EnterCriticalSection(&mCrit);}; 84 | void Release(){LeaveCriticalSection(&mCrit);}; 85 | 86 | private: 87 | CRITICAL_SECTION mCrit; 88 | #elif defined(__GNUC__) 89 | 90 | public: 91 | Lock(){pthread_mutex_init(&mCrit, 0); }; 92 | ~Lock(){pthread_mutex_destroy(&mCrit); }; 93 | void Aquire(){pthread_mutex_lock(&mCrit);}; 94 | void Release(){pthread_mutex_unlock(&mCrit);}; 95 | 96 | private: 97 | pthread_mutex_t mCrit; 98 | #endif 99 | }; 100 | 101 | 102 | class ScopedLock : public Lock 103 | { 104 | public: 105 | ScopedLock(Lock& lock):pLock_(&lock) {lock.Aquire();}; 106 | ~ScopedLock(){ if(pLock_) pLock_->Release(); pLock_=0; }; 107 | private: 108 | Lock* pLock_; 109 | }; 110 | 111 | 112 | 113 | //threading 114 | inline uint32 getCurrentProcId() 115 | { 116 | #ifdef OS_WIN 117 | return GetCurrentProcessId(); 118 | #elif defined(__GNUC__) 119 | return getpid(); 120 | #endif 121 | } 122 | 123 | inline uint32 getCurrentThreadId() 124 | { 125 | #ifdef OS_WIN 126 | return GetCurrentThreadId(); 127 | #elif defined(__GNUC__) 128 | return pthread_self(); 129 | #endif 130 | } 131 | 132 | 133 | 134 | // When enough events are collected, they are handed (in bulk) to 135 | // the output callback. If no callback is set, the output will be 136 | // silently dropped. The callback must be thread safe. 137 | //typedef RefCountedData std::string*; 138 | //typedef base::Callback OutputCallback; 139 | void OutputCallback(const char*); 140 | 141 | // The trace buffer does not flush dynamically, so when it fills up, 142 | // subsequent trace events will be dropped. This callback is generated when 143 | // the trace buffer is full. The callback must be thread safe. 144 | //typedef base::Callback BufferFullCallback; 145 | void BufferFullCallback(); 146 | } 147 | 148 | #endif -------------------------------------------------------------------------------- /canvas-pixel-picking/httpd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Copyright (c) 2011, The Native Client Authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style license that can be 5 | # found in the LICENSE file. 6 | # 7 | 8 | """A tiny web server. 9 | 10 | This is intended to be used for testing, and only run from within the examples 11 | directory. 12 | """ 13 | 14 | import BaseHTTPServer 15 | import logging 16 | import os 17 | import SimpleHTTPServer 18 | import SocketServer 19 | import sys 20 | import urlparse 21 | 22 | logging.getLogger().setLevel(logging.INFO) 23 | 24 | # Using 'localhost' means that we only accept connections 25 | # via the loop back interface. 26 | SERVER_PORT = 5103 27 | SERVER_HOST = '' 28 | 29 | # We only run from the examples directory (the one that contains scons-out), so 30 | # that not too much is exposed via this HTTP server. Everything in the 31 | # directory is served, so there should never be anything potentially sensitive 32 | # in the serving directory, especially if the machine might be a 33 | # multi-user machine and not all users are trusted. We only serve via 34 | # the loopback interface. 35 | 36 | SAFE_DIR_COMPONENTS = ['nacl'] 37 | SAFE_DIR_SUFFIX = apply(os.path.join, SAFE_DIR_COMPONENTS) 38 | 39 | def SanityCheckDirectory(): 40 | return 41 | logging.error('httpd.py should only be run from the %s', SAFE_DIR_SUFFIX) 42 | logging.error('directory for testing purposes.') 43 | logging.error('We are currently in %s', os.getcwd()) 44 | sys.exit(1) 45 | 46 | 47 | # An HTTP server that will quit when |is_running| is set to False. We also use 48 | # SocketServer.ThreadingMixIn in order to handle requests asynchronously for 49 | # faster responses. 50 | class QuittableHTTPServer(SocketServer.ThreadingMixIn, 51 | BaseHTTPServer.HTTPServer): 52 | def serve_forever(self, timeout=0.5): 53 | self.is_running = True 54 | self.timeout = timeout 55 | while self.is_running: 56 | self.handle_request() 57 | 58 | def shutdown(self): 59 | self.is_running = False 60 | return 1 61 | 62 | 63 | # "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not 64 | # exist in |str|, then the entire |str| is the key and the value is set to an 65 | # empty string. 66 | def KeyValuePair(str, sep='='): 67 | if sep in str: 68 | return str.split(sep) 69 | else: 70 | return [str, ''] 71 | 72 | 73 | # A small handler that looks for '?quit=1' query in the path and shuts itself 74 | # down if it finds that parameter. 75 | class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): 76 | def do_GET(self): 77 | (_, _, _, query, _) = urlparse.urlsplit(self.path) 78 | url_params = dict([KeyValuePair(key_value) 79 | for key_value in query.split('&')]) 80 | if 'quit' in url_params and '1' in url_params['quit']: 81 | self.send_response(200, 'OK') 82 | self.send_header('Content-type', 'text/html') 83 | self.send_header('Content-length', '0') 84 | self.end_headers() 85 | self.server.shutdown() 86 | return 87 | 88 | SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) 89 | 90 | 91 | def Run(server_address, 92 | server_class=QuittableHTTPServer, 93 | handler_class=QuittableHTTPHandler): 94 | httpd = server_class(server_address, handler_class) 95 | logging.info("Starting local server on port %d", server_address[1]) 96 | logging.info("To shut down send http://localhost:%d?quit=1", 97 | server_address[1]) 98 | try: 99 | httpd.serve_forever() 100 | except KeyboardInterrupt: 101 | logging.info("Received keyboard interrupt.") 102 | httpd.server_close() 103 | 104 | logging.info("Shutting down local server on port %d", server_address[1]) 105 | 106 | 107 | if __name__ == '__main__': 108 | SanityCheckDirectory() 109 | if len(sys.argv) > 1: 110 | Run((SERVER_HOST, int(sys.argv[1]))) 111 | else: 112 | Run((SERVER_HOST, SERVER_PORT)) 113 | sys.exit(0) 114 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/httpd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Copyright (c) 2011, The Native Client Authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style license that can be 5 | # found in the LICENSE file. 6 | # 7 | 8 | """A tiny web server. 9 | 10 | This is intended to be used for testing, and only run from within the examples 11 | directory. 12 | """ 13 | 14 | import BaseHTTPServer 15 | import logging 16 | import os 17 | import SimpleHTTPServer 18 | import SocketServer 19 | import sys 20 | import urlparse 21 | 22 | logging.getLogger().setLevel(logging.INFO) 23 | 24 | # Using 'localhost' means that we only accept connections 25 | # via the loop back interface. 26 | SERVER_PORT = 8080 27 | SERVER_HOST = '' 28 | 29 | # We only run from the examples directory (the one that contains scons-out), so 30 | # that not too much is exposed via this HTTP server. Everything in the 31 | # directory is served, so there should never be anything potentially sensitive 32 | # in the serving directory, especially if the machine might be a 33 | # multi-user machine and not all users are trusted. We only serve via 34 | # the loopback interface. 35 | 36 | SAFE_DIR_COMPONENTS = ['nacl'] 37 | SAFE_DIR_SUFFIX = apply(os.path.join, SAFE_DIR_COMPONENTS) 38 | 39 | def SanityCheckDirectory(): 40 | return 41 | logging.error('httpd.py should only be run from the %s', SAFE_DIR_SUFFIX) 42 | logging.error('directory for testing purposes.') 43 | logging.error('We are currently in %s', os.getcwd()) 44 | sys.exit(1) 45 | 46 | 47 | # An HTTP server that will quit when |is_running| is set to False. We also use 48 | # SocketServer.ThreadingMixIn in order to handle requests asynchronously for 49 | # faster responses. 50 | class QuittableHTTPServer(SocketServer.ThreadingMixIn, 51 | BaseHTTPServer.HTTPServer): 52 | def serve_forever(self, timeout=0.5): 53 | self.is_running = True 54 | self.timeout = timeout 55 | while self.is_running: 56 | self.handle_request() 57 | 58 | def shutdown(self): 59 | self.is_running = False 60 | return 1 61 | 62 | 63 | # "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not 64 | # exist in |str|, then the entire |str| is the key and the value is set to an 65 | # empty string. 66 | def KeyValuePair(str, sep='='): 67 | if sep in str: 68 | return str.split(sep) 69 | else: 70 | return [str, ''] 71 | 72 | 73 | # A small handler that looks for '?quit=1' query in the path and shuts itself 74 | # down if it finds that parameter. 75 | class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): 76 | def do_GET(self): 77 | (_, _, _, query, _) = urlparse.urlsplit(self.path) 78 | url_params = dict([KeyValuePair(key_value) 79 | for key_value in query.split('&')]) 80 | if 'quit' in url_params and '1' in url_params['quit']: 81 | self.send_response(200, 'OK') 82 | self.send_header('Content-type', 'text/html') 83 | self.send_header('Content-length', '0') 84 | self.end_headers() 85 | self.server.shutdown() 86 | return 87 | 88 | SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) 89 | 90 | 91 | def Run(server_address, 92 | server_class=QuittableHTTPServer, 93 | handler_class=QuittableHTTPHandler): 94 | httpd = server_class(server_address, handler_class) 95 | logging.info("Starting local server on port %d", server_address[1]) 96 | logging.info("To shut down send http://localhost:%d?quit=1", 97 | server_address[1]) 98 | try: 99 | httpd.serve_forever() 100 | except KeyboardInterrupt: 101 | logging.info("Received keyboard interrupt.") 102 | httpd.server_close() 103 | 104 | logging.info("Shutting down local server on port %d", server_address[1]) 105 | 106 | 107 | if __name__ == '__main__': 108 | SanityCheckDirectory() 109 | if len(sys.argv) > 1: 110 | Run((SERVER_HOST, int(sys.argv[1]))) 111 | else: 112 | Run((SERVER_HOST, SERVER_PORT)) 113 | sys.exit(0) 114 | -------------------------------------------------------------------------------- /patching-system/server/httpd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Copyright (c) 2011, The Native Client Authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style license that can be 5 | # found in the LICENSE file. 6 | # 7 | 8 | """A tiny web server. 9 | 10 | This is intended to be used for testing, and only run from within the examples 11 | directory. 12 | """ 13 | 14 | import BaseHTTPServer 15 | import logging 16 | import os 17 | import SimpleHTTPServer 18 | import SocketServer 19 | import sys 20 | import urlparse 21 | 22 | logging.getLogger().setLevel(logging.INFO) 23 | 24 | # Using 'localhost' means that we only accept connections 25 | # via the loop back interface. 26 | SERVER_PORT = 8080 27 | SERVER_HOST = '' 28 | 29 | # We only run from the examples directory (the one that contains scons-out), so 30 | # that not too much is exposed via this HTTP server. Everything in the 31 | # directory is served, so there should never be anything potentially sensitive 32 | # in the serving directory, especially if the machine might be a 33 | # multi-user machine and not all users are trusted. We only serve via 34 | # the loopback interface. 35 | 36 | SAFE_DIR_COMPONENTS = ['nacl'] 37 | SAFE_DIR_SUFFIX = apply(os.path.join, SAFE_DIR_COMPONENTS) 38 | 39 | def SanityCheckDirectory(): 40 | return 41 | logging.error('httpd.py should only be run from the %s', SAFE_DIR_SUFFIX) 42 | logging.error('directory for testing purposes.') 43 | logging.error('We are currently in %s', os.getcwd()) 44 | sys.exit(1) 45 | 46 | 47 | # An HTTP server that will quit when |is_running| is set to False. We also use 48 | # SocketServer.ThreadingMixIn in order to handle requests asynchronously for 49 | # faster responses. 50 | class QuittableHTTPServer(SocketServer.ThreadingMixIn, 51 | BaseHTTPServer.HTTPServer): 52 | def serve_forever(self, timeout=0.5): 53 | self.is_running = True 54 | self.timeout = timeout 55 | while self.is_running: 56 | self.handle_request() 57 | 58 | def shutdown(self): 59 | self.is_running = False 60 | return 1 61 | 62 | 63 | # "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not 64 | # exist in |str|, then the entire |str| is the key and the value is set to an 65 | # empty string. 66 | def KeyValuePair(str, sep='='): 67 | if sep in str: 68 | return str.split(sep) 69 | else: 70 | return [str, ''] 71 | 72 | 73 | # A small handler that looks for '?quit=1' query in the path and shuts itself 74 | # down if it finds that parameter. 75 | class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): 76 | def do_GET(self): 77 | (_, _, _, query, _) = urlparse.urlsplit(self.path) 78 | url_params = dict([KeyValuePair(key_value) 79 | for key_value in query.split('&')]) 80 | if 'quit' in url_params and '1' in url_params['quit']: 81 | self.send_response(200, 'OK') 82 | self.send_header('Content-type', 'text/html') 83 | self.send_header('Content-length', '0') 84 | self.end_headers() 85 | self.server.shutdown() 86 | return 87 | 88 | SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) 89 | 90 | 91 | def Run(server_address, 92 | server_class=QuittableHTTPServer, 93 | handler_class=QuittableHTTPHandler): 94 | httpd = server_class(server_address, handler_class) 95 | logging.info("Starting local server on port %d", server_address[1]) 96 | logging.info("To shut down send http://localhost:%d?quit=1", 97 | server_address[1]) 98 | try: 99 | httpd.serve_forever() 100 | except KeyboardInterrupt: 101 | logging.info("Received keyboard interrupt.") 102 | httpd.server_close() 103 | 104 | logging.info("Shutting down local server on port %d", server_address[1]) 105 | 106 | 107 | if __name__ == '__main__': 108 | SanityCheckDirectory() 109 | if len(sys.argv) > 1: 110 | Run((SERVER_HOST, int(sys.argv[1]))) 111 | else: 112 | Run((SERVER_HOST, SERVER_PORT)) 113 | sys.exit(0) 114 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/coreGame.js: -------------------------------------------------------------------------------- 1 | 2 | //--------------------------------- 3 | function xhrGet(reqUri,reqCred,callback) 4 | { 5 | var contentType = "application/x-www-form-urlencoded; charset=utf-8"; 6 | var xhr = new XMLHttpRequest(); 7 | xhr.open("GET", reqUri, true); 8 | xhr.overrideMimeType('text/plain; charset=x-user-defined'); 9 | xhr.onreadystatechange = function() 10 | { 11 | if (xhr.readyState == 4 && xhr.responseText !="") 12 | { 13 | if(callback != null) 14 | callback(xhr); 15 | } 16 | }; 17 | if(reqCred) 18 | xhr.withCredentials = "true"; 19 | xhr.send(); 20 | } 21 | 22 | 23 | //------------------ 24 | var cv; 25 | var gCanvas_context ; 26 | var pPos={x:3193,y: 3178}; 27 | var pDir={x:1,y:1}; 28 | var pRotAngle = 0.0; 29 | var vDist = 50; 30 | var speed = 3; 31 | var mrdoob_stats = null; 32 | //------------------------------------- 33 | 34 | function init() 35 | { 36 | cv = document.getElementById('cvs'); 37 | gCanvas_context = cv.getContext('2d'); 38 | 39 | 40 | 41 | window.addEventListener('keydown', this.keydown, false); 42 | window.addEventListener('keyup', this.keyup, false); 43 | 44 | //ISSUE a command to fetch all the data linearly by name 45 | gMap.load("../data/map.json"); 46 | 47 | mrdoob_stats = new Stats(); 48 | mrdoob_stats.getDomElement().style.position = 'absolute'; 49 | mrdoob_stats.getDomElement().style.left = cv.style.left; 50 | mrdoob_stats.getDomElement().style.top = "155px"; 51 | document.body.appendChild(mrdoob_stats.getDomElement()); 52 | 53 | } 54 | //------------------------------------- 55 | function adjustRot() 56 | { 57 | var cs = Math.cos(pRotAngle); 58 | var ss = Math.sin(pRotAngle); 59 | 60 | var x = 1; 61 | var y = 0; 62 | var x0 = cs * x + ss * y; 63 | var y0 = -ss * x + cs * y; 64 | 65 | pDir.x = x0; 66 | pDir.y = y0; 67 | 68 | } 69 | //------------------------------------- 70 | var kDown={}; 71 | function keydown(event) 72 | { 73 | kDown[event.keyCode]=1; 74 | } 75 | //------------------------------------- 76 | function keyup(event) 77 | { 78 | kDown[event.keyCode]=0; 79 | } 80 | 81 | //------------------------------------- 82 | function step() 83 | { 84 | requestAnimFrame( step ); 85 | mrdoob_stats.update(); 86 | draw(); 87 | 88 | //adjust inputs! 89 | 90 | //if(kDown[87]) 91 | { 92 | pPos.x += pDir.x * speed; 93 | pPos.y += pDir.y * speed; 94 | } 95 | /* else if(kDown[83]) 96 | { 97 | pPos.x += pDir.x * -speed; 98 | pPos.y += pDir.y * -speed; 99 | } 100 | */ 101 | if(kDown[65]) 102 | { 103 | pRotAngle-=0.05; 104 | adjustRot(); 105 | } 106 | else if(kDown[68]) 107 | { 108 | pRotAngle+=0.05; 109 | adjustRot(); 110 | } 111 | 112 | 113 | //floor our values to keep our positions in integer space 114 | pPos.x = Math.floor(pPos.x); 115 | pPos.y = Math.floor(pPos.y); 116 | 117 | if(pPos.x <=0) pPos.x = 0; 118 | if(pPos.y <=0) pPos.y = 0; 119 | if(pPos.x >=gMap.pixelSize.x) pPos.x = gMap.pixelSize.x; 120 | if(pPos.y >=gMap.pixelSize.y) pPos.y = gMap.pixelSize.y; 121 | } 122 | 123 | //------------------------------------- 124 | function draw() 125 | { 126 | var cWidth = 1000; 127 | var cHeight = 1000; 128 | var hW = cWidth/2; 129 | var hH = cHeight/2; 130 | 131 | gCanvas_context.fillStyle = "White"; 132 | gCanvas_context.fillRect(0,0,cWidth,cHeight); 133 | 134 | gMap.viewRect.x = (pPos.x - hW); 135 | gMap.viewRect.y = (pPos.y - hH); 136 | gMap.viewRect.w = cWidth; 137 | gMap.viewRect.h = cHeight; 138 | gMap.draw(gCanvas_context); 139 | 140 | //draw our little dude guy 141 | gCanvas_context.fillStyle = "Red"; 142 | gCanvas_context.fillRect(pPos.x-2 - gMap.viewRect.x ,pPos.y-2- gMap.viewRect.y ,5,5); 143 | //draw directional line 144 | gCanvas_context.strokeStyle = "Blue"; 145 | gCanvas_context.beginPath(); 146 | gCanvas_context.moveTo(pPos.x - gMap.viewRect.x, pPos.y - gMap.viewRect.y); 147 | gCanvas_context.lineTo((pPos.x + pDir.x *vDist)- gMap.viewRect.x, (pPos.y + pDir.y *vDist)- gMap.viewRect.y); 148 | gCanvas_context.stroke(); 149 | } 150 | -------------------------------------------------------------------------------- /patching-system/build/gen_patch.py: -------------------------------------------------------------------------------- 1 | 2 | import subprocess 3 | import os.path 4 | from os import listdir 5 | from os.path import isfile, isdir, join 6 | from filecmp import dircmp 7 | import json 8 | import sys 9 | import shutil 10 | ''' 11 | This will analyze two directories and report the list of files that are different. 12 | ''' 13 | #======================================================== 14 | #in reality these should be passed in from your build tool 15 | 16 | dir0_buildNum = 0 17 | dir0 = "./" + str(dir0_buildNum) 18 | 19 | dir1_buildNum = 1 20 | dir1 = "./" + str(dir1_buildNum) 21 | #======================================================== 22 | #some helper functions 23 | def give_files(mypath): 24 | fs = [] 25 | for f in listdir(mypath): 26 | if (isdir(join(mypath,f))): 27 | ks = give_files(join(mypath,f)) 28 | fs.extend(ks) 29 | if isfile(join(mypath,f)) : 30 | fs.append(join(mypath,f)) 31 | return fs 32 | 33 | def safe_copy_file(src,dst): 34 | dstfldr = dst.replace(os.path.basename(dst),"") 35 | if not os.path.exists(dstfldr): os.makedirs(dstfldr) 36 | shutil.copyfile(src,dst) 37 | #======================================================== 38 | class Build(object): 39 | def __init__(self): 40 | self.buildnum = 0 41 | self.add_files=[] 42 | self.del_files=[] 43 | self.patch_files=[] 44 | buildnum=0 45 | add_files=[] 46 | del_files=[] 47 | patch_files=[] 48 | 49 | latestBuild = Build() 50 | #============================================================== 51 | #http://docs.python.org/library/filecmp.html 52 | def print_diff_files(dcmp): 53 | for name in dcmp.left_only: 54 | fname = dcmp.left +"/" + name 55 | if isdir(fname): 56 | latestBuild.del_files.extend(give_files(fname)) 57 | else: 58 | latestBuild.del_files.append(dcmp.left +"/" + name) 59 | for name in dcmp.right_only: 60 | fname = dcmp.right +"/" + name 61 | if isdir(fname): 62 | latestBuild.add_files.extend(give_files(fname)) 63 | else: 64 | latestBuild.add_files.append(dcmp.right +"/" + name) 65 | for name in dcmp.diff_files: 66 | latestBuild.add_files.append(dcmp.right +"/" + name) 67 | for sub_dcmp in dcmp.subdirs.values(): 68 | print_diff_files(sub_dcmp) 69 | 70 | dcmp = dircmp(dir0, dir1) 71 | print_diff_files(dcmp) 72 | 73 | 74 | #==================================================================== 75 | #extract the add/diff files and compress them in a zip file 76 | print 'creating zip of differences' 77 | 78 | import zipfile 79 | zipFName = str(dir0_buildNum) + "_" + str(dir1_buildNum) + ".patch.zip" 80 | zf = zipfile.ZipFile(zipFName, mode='w') 81 | try: 82 | for file in latestBuild.add_files: 83 | 84 | zf.write(file,arcname=file.replace(dir1,"")) 85 | print file 86 | finally: 87 | zf.close() 88 | print "zip created" 89 | 90 | #create a leaf build name 91 | latestBuild.add_files[:] = [] 92 | latestBuild.add_files.append(zipFName) 93 | #copy the file to the build server 94 | safe_copy_file("./" + zipFName,"../server/patches/" + zipFName) 95 | os.remove(zipFName) 96 | 97 | #========================================================================= 98 | #open our manifest file, add this to it. 99 | 100 | #Helper function to output and optionally pretty print JSON. 101 | _JSON_ENCODER = json.JSONEncoder() 102 | _JSON_ENCODER.indent = 4 103 | _JSON_ENCODER.sort_keys = True 104 | def tojson(python_object): 105 | return _JSON_ENCODER.encode(python_object) 106 | 107 | #open the existing file list 108 | mani_file = "../server/filelist.json" 109 | 110 | build_mani={} 111 | try: 112 | f = open(mani_file,'r') 113 | build_mani = json.loads(f.read()) 114 | f.close() 115 | except: 116 | build_mani={} 117 | build_mani['builds'] = [] 118 | 119 | vbd={} 120 | #do we already have this build in the list? 121 | for build in build_mani['builds']: 122 | if build['buildnum'] == dir1_buildNum: 123 | vbd = build 124 | 125 | #if this is a new build, append it 126 | if len(vbd.keys()) == 0: 127 | build_mani['builds'].append(vbd); 128 | 129 | vbd['buildnum'] = dir1_buildNum 130 | vbd['add-files'] = latestBuild.add_files 131 | 132 | 133 | 134 | f = open(mani_file,"w") 135 | f.write(json.dumps(build_mani)) 136 | f.close() 137 | 138 | -------------------------------------------------------------------------------- /needle.js/tests/perf_needle_orig.html: -------------------------------------------------------------------------------- 1 | 14 | 15 |
This test will time Needle.js per-event overhead as the first version. In a seperate file to ensure manual reloads to cause lingering GC overhead...

16 | 17 |
working...
18 | 19 | 20 | 21 | 66 | 167 | 168 | -------------------------------------------------------------------------------- /stat_tracker/2.server-gather/main.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement #for blobstore 2 | from google.appengine.api import files #for blobstore 3 | from google.appengine.ext import blobstore #for blobstore 4 | 5 | from google.appengine.api import backends #needed for backends 6 | import stats_backend #needed for backends 7 | from google.appengine.api import urlfetch #needed for backends 8 | 9 | import os; 10 | import webapp2 #needed for backends 11 | import cgi 12 | import datetime 13 | import urllib 14 | import json 15 | import logging 16 | import wsgiref.handlers 17 | from types import * 18 | 19 | _BACKEND_NAME='statgather' 20 | #needed for backends 21 | if backends.get_backend() == _BACKEND_NAME: 22 | _stats = stats_backend.StatsGather() 23 | 24 | def tojson(python_object): 25 | """Helper function to output and optionally pretty print JSON.""" 26 | return json.JSONEncoder().encode(python_object) 27 | 28 | def fromjson(msg): 29 | """Helper function to ingest JSON.""" 30 | try: 31 | return json.loads(msg) 32 | except Exception, e: 33 | raise Exception('Unable to parse as JSON: %s' % msg) 34 | 35 | 36 | #----------------------------------------------------- 37 | class StatsHandler(webapp2.RequestHandler): 38 | def post(self,fcn): 39 | 40 | if(fcn == "add"): 41 | type = self.request.get('type',"unknown") 42 | name = self.request.get('name',"unknown") 43 | ip = self.request.remote_addr 44 | metadata = self.request.body 45 | backendURL = backends.get_url(backend=_BACKEND_NAME, instance=None, protocol='HTTP') 46 | url = '%s/k/add?type=%s&name=%s' % (backendURL, type,name) 47 | 48 | payload = metadata 49 | 50 | resp = urlfetch.fetch(url=url, 51 | payload=payload, 52 | method=urlfetch.POST, 53 | deadline=60 #CLM is this OK practice? 54 | #headers={'Content-Type': 'application/json'} 55 | ) 56 | self.response.set_status(resp.status_code) 57 | self.response.out.write(resp.content) 58 | logging.info('%s -> %s -> %s' % (repr(payload), url, resp.content)) 59 | 60 | def get(self,fcn): 61 | 62 | if(fcn == "blobs"): 63 | # self.postBackendFlush() 64 | gqlQuery = blobstore.BlobInfo.gql("ORDER BY creation DESC") 65 | blobs = gqlQuery.fetch(10) 66 | 67 | outStr = "[" 68 | for blob in blobs: 69 | blob_reader = blobstore.BlobReader(blob.key()) 70 | value = blob_reader.read() 71 | #logging.info("VVVVVVV" + value) 72 | outStr = outStr + value 73 | outStr = outStr + "]" 74 | 75 | #pass back to the client for display 76 | self.response.headers['Content-Type'] = 'application/json' 77 | self.response.out.write(outStr) 78 | elif(fcn == "flush"): 79 | self.postBackendFlush() 80 | else: 81 | self.response.out.write("{}") 82 | 83 | def postBackendFlush(self): 84 | backendURL = backends.get_url(backend=_BACKEND_NAME, instance=None, protocol='HTTP') 85 | url = '%s/k/flush' % (backendURL) 86 | 87 | payload = "{}" 88 | #rpc = urlfetch.create_rpc() 89 | #urlfetch.make_fetch_call 90 | resp = urlfetch.fetch(url=url, 91 | payload=payload, 92 | method=urlfetch.POST, 93 | deadline=60 94 | #headers={'Content-Type': 'application/json'} 95 | ) 96 | 97 | 98 | #----------------------------------------------------- 99 | 100 | 101 | #the backend handler 102 | class HybridStatsHandler(webapp2.RequestHandler): 103 | def post(self,fcn): 104 | if(fcn == "add"): 105 | type = self.request.get('type',"unknown") 106 | name = self.request.get('name',"unknown") 107 | #logging.info( "====BODY: " +self.request.body) 108 | #params = fromjson(self.request.body) #CLM this has a problem. the incoming data isn't formatted nicely due to it's header being x-www-form-urlencoded 109 | ip = self.request.remote_addr 110 | metadata = self.request.body 111 | _stats.addGameEvent(type,name,metadata,"now") 112 | self.response.out.write("success") 113 | elif(fcn == "flush"): 114 | _stats.forceFlush() 115 | self.response.out.write("success") 116 | 117 | def get(self,fcn): 118 | self.response.out.write("ugg") 119 | 120 | 121 | 122 | # handler common to frontends and backends 123 | handlers = [ 124 | ] 125 | 126 | if not backends.get_backend(): 127 | # frontend specific handlers 128 | handlers.extend([ 129 | ('/s/(.*)', StatsHandler) 130 | ]) 131 | elif backends.get_backend() == _BACKEND_NAME: 132 | # 'stats' backend specific handlers 133 | handlers.extend([ 134 | ('/k/(.*)', HybridStatsHandler) 135 | ]) 136 | 137 | app = webapp2.WSGIApplication(handlers, debug=True) 138 | 139 | -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/GenSpriteHull.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 26 | 29 | 32 | 35 | 38 | 41 | 53 | 56 | 59 | 62 | 71 | 74 | 77 | 80 | 83 | 86 | 89 | 92 | 93 | 101 | 104 | 107 | 110 | 113 | 116 | 134 | 137 | 140 | 143 | 155 | 158 | 161 | 164 | 167 | 170 | 173 | 176 | 177 | 178 | 179 | 180 | 181 | 184 | 185 | 188 | 189 | 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/0_forward/TILEDmap.js: -------------------------------------------------------------------------------- 1 | 2 | var TILEDmap = Class.extend({ 3 | currMapData: null, 4 | tileSets: new Array(), 5 | viewRect: { 6 | "x": 0, 7 | "y": 0, 8 | "w": 1000, 9 | "h": 1000 10 | }, 11 | numXTiles: 100, 12 | numYTiles: 100, 13 | tileSize: { 14 | "x": 64, 15 | "y": 64 16 | }, 17 | pixelSize: { 18 | "x": 64, 19 | "y": 64 20 | }, 21 | tileImg:null, 22 | imgLoadCount:0, 23 | preCacheCanvasArray:null, 24 | fullyLoaded:false, 25 | //--------------------------- 26 | load: function (map) 27 | { 28 | 29 | xhrGet(map, false,function(data) 30 | { 31 | gMap.parseMapJSON(data.response); 32 | 33 | }); 34 | }, 35 | //--------------------------- 36 | _tempInput:null, 37 | parseMapJSON:function(mapJSON) 38 | { 39 | this.currMapData = JSON.parse( mapJSON ); 40 | 41 | var map = this.currMapData; 42 | this.numXTiles = map.width; 43 | this.numYTiles = map.height; 44 | this.tileSize.x = map.tilewidth; 45 | this.tileSize.y = map.tileheight; 46 | this.pixelSize.x = this.numXTiles * this.tileSize.x; 47 | this.pixelSize.y = this.numYTiles * this.tileSize.y; 48 | 49 | //load our tilesets if we are a client. 50 | var gMap = this; 51 | for (var i = 0; i < map.tilesets.length; i++) 52 | { 53 | var img = new Image(); 54 | img.onload = new function() {gMap.imgLoadCount++;}; 55 | img.src = "../data/" + map.tilesets[i].image.replace(/^.*[\\\/]/, ''); 56 | var ts = { 57 | "firstgid": map.tilesets[i].firstgid, 58 | "image": img, 59 | "imageheight": map.tilesets[i].imageheight, 60 | "imagewidth": map.tilesets[i].imagewidth, 61 | "name": map.tilesets[i].name, 62 | "numXTiles": Math.floor(map.tilesets[i].imagewidth / this.tileSize.x), 63 | "numYTiles": Math.floor(map.tilesets[i].imageheight / this.tileSize.y) 64 | }; 65 | this.tileSets.push(ts); 66 | 67 | 68 | //clm precache the bg 69 | checkWait( 70 | function() 71 | { 72 | return gMap.imgLoadCount == gMap.tileSets.length; 73 | }, 74 | function () 75 | { 76 | gMap.fullyLoaded = true; 77 | }); 78 | 79 | } 80 | }, 81 | //--------------------------- 82 | getTilePacket: function (tileIndex) { 83 | var pkt = { 84 | "img": null, 85 | "px": 0, 86 | "py": 0 87 | }; 88 | var i = 0; 89 | for (i = this.tileSets.length - 1; i >= 0; i--) { 90 | if (this.tileSets[i].firstgid <= tileIndex) break; 91 | } 92 | 93 | pkt.img = this.tileSets[i].image; 94 | var localIdx = tileIndex - this.tileSets[i].firstgid; 95 | var lTileX = Math.floor(localIdx % this.tileSets[i].numXTiles); 96 | var lTileY = Math.floor(localIdx / this.tileSets[i].numXTiles); 97 | pkt.px = (lTileX * this.tileSize.x); 98 | pkt.py = (lTileY * this.tileSize.y); 99 | 100 | return pkt; 101 | }, 102 | //--------------------------- 103 | intersectRect:function (r1, r2) { 104 | return !(r2.left > r1.right || 105 | r2.right < r1.left || 106 | r2.top > r1.bottom || 107 | r2.bottom < r1.top); 108 | }, 109 | //--------------------------- 110 | draw: function (ctx) 111 | { // 112 | if(!this.fullyLoaded) return; 113 | 114 | 115 | for (var layerIdx = 0; layerIdx < this.currMapData.layers.length; layerIdx++) 116 | { 117 | if (this.currMapData.layers[layerIdx].type != "tilelayer") continue; 118 | 119 | var dat = this.currMapData.layers[layerIdx].data; 120 | //find what the tileIndexOffset is for this layer 121 | for (var tileIDX = 0; tileIDX < dat.length; tileIDX++) { 122 | var tID = dat[tileIDX]; 123 | if (tID == 0) continue; 124 | 125 | var tPKT = this.getTilePacket(tID); 126 | 127 | //test if this tile is within our world bounds 128 | var worldX = Math.floor(tileIDX % this.numXTiles) * this.tileSize.x; 129 | var worldY = Math.floor(tileIDX / this.numXTiles) * this.tileSize.y; 130 | if ((worldX + this.tileSize.x) < this.viewRect.x || (worldY + this.tileSize.y) < this.viewRect.y || worldX > this.viewRect.x + this.viewRect.w || worldY > this.viewRect.y + this.viewRect.h) continue; 131 | 132 | //adjust all the visible tiles to draw at canvas origin. 133 | worldX -= this.viewRect.x; 134 | worldY -= this.viewRect.y; 135 | 136 | // Nine arguments: the element, source (x,y) coordinates, source width and 137 | // height (for cropping), destination (x,y) coordinates, and destination width 138 | // and height (resize). 139 | ctx.drawImage(tPKT.img, tPKT.px, tPKT.py, this.tileSize.x, this.tileSize.y, worldX, worldY, this.tileSize.x, this.tileSize.y); 140 | 141 | } 142 | } 143 | }, 144 | }); 145 | 146 | var gMap = new TILEDmap(); -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | A simple program that will calculate the convex hull of a sprite based upon alpha. 4 | 5 | */ 6 | 7 | #include 8 | #include "imgHelper.h" 9 | 10 | struct point 11 | { 12 | int x; 13 | int y; 14 | bool operator <(const point &p) const { 15 | return x < p.x || (x == p.x && y < p.y); 16 | } 17 | 18 | }; 19 | 20 | //FROM http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain 21 | // Implementation of Andrew's monotone chain 2D convex hull algorithm. 22 | // Asymptotic complexity: O(n log n). 23 | // Practical performance: 0.5-1.0 seconds for n=1000000 on a 1GHz machine. 24 | #include 25 | 26 | //----------------------------------- 27 | // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product. 28 | // Returns a positive value, if OAB makes a counter-clockwise turn, 29 | // negative for clockwise turn, and zero if the points are collinear. 30 | int cross(const point &O, const point &A, const point &B) 31 | { 32 | return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x); 33 | } 34 | //----------------------------------- 35 | // Returns a list of points on the convex hull in counter-clockwise order. 36 | // Note: the last point in the returned list is the same as the first one. 37 | std::vector convex_hull(std::vector P) 38 | { 39 | int n = P.size(), k = 0; 40 | std::vector H(2*n); 41 | 42 | // Sort points lexicographically 43 | sort(P.begin(), P.end()); 44 | 45 | // Build lower hull 46 | for (int i = 0; i < n; i++) { 47 | while (k >= 2 && cross(H[k-2], H[k-1], P[i]) <= 0) k--; 48 | H[k++] = P[i]; 49 | } 50 | 51 | // Build upper hull 52 | for (int i = n-2, t = k+1; i >= 0; i--) { 53 | while (k >= t && cross(H[k-2], H[k-1], P[i]) <= 0) k--; 54 | H[k++] = P[i]; 55 | } 56 | 57 | H.resize(k); 58 | return H; 59 | } 60 | //----------------------------------- 61 | 62 | void calcOuterPoints(ImageData& id, std::vector& outPoints, const uint32 threshold) 63 | { 64 | //walk each scanline 65 | for(int y = 0; y < id.height; y++) 66 | { 67 | int idx = (y * id.width) * 4; 68 | 69 | int start = 0; 70 | //find the outer bounds of this scan-line 71 | for(int x = 0; x < id.width; x++) 72 | { 73 | if(id.pImgData[idx + 3] >= threshold) 74 | { 75 | point pt; 76 | pt.x = x; 77 | pt.y = y; 78 | outPoints.push_back(pt); 79 | start = x; 80 | break; 81 | } 82 | 83 | idx+=4; 84 | } 85 | 86 | //find the outer bounds of this scan-line 87 | idx = (((y+1) * id.width) * 4) -4; 88 | for(int x = id.width-1; x >start; x--) 89 | { 90 | if(id.pImgData[idx + 3] != 0) 91 | { 92 | point pt; 93 | pt.x = x; 94 | pt.y = y; 95 | outPoints.push_back(pt); 96 | break; 97 | } 98 | 99 | idx-=4; 100 | } 101 | 102 | } 103 | } 104 | //----------------------------------- 105 | void writeJSON(const char* pFilename, std::vector& pts) 106 | { 107 | char outName[512]; 108 | sprintf(outName,"%s.json",pFilename); 109 | 110 | char outStr[128]; 111 | FILE* pOut = fopen(outName,"wt"); 112 | 113 | sprintf(outStr,"{\"name\":\"%s\", \"hull\":[{\"x\":%i,\"y\":%i}",pFilename,pts[0].x, pts[0].y); 114 | fwrite(outStr,strlen(outStr),1,pOut); 115 | 116 | for(int i =1; i < pts.size();i++) 117 | { 118 | sprintf(outStr,", {\"x\":%i,\"y\":%i}",pts[i].x, pts[i].y); 119 | fwrite(outStr,strlen(outStr),1,pOut); 120 | } 121 | 122 | sprintf(outStr,"]}\n"); 123 | fwrite(outStr,strlen(outStr),1,pOut); 124 | 125 | fclose(pOut); 126 | } 127 | 128 | //----------------------------------- 129 | //RUN with "hullbuild.exe textures/3.png 50" 130 | int main(int argc, char *argv[]) 131 | { 132 | 133 | if (argc < 3) 134 | { 135 | fprintf(stderr, 136 | "\nGenSpriteHull \n\n" 137 | ); 138 | 139 | return 0; 140 | } 141 | 142 | 143 | 144 | const char *pFilename = argv[1]; 145 | const int threshold = atoi(argv[2]); 146 | 147 | 148 | ImageData id; 149 | 150 | if(!loadImageData(pFilename, id)) 151 | { 152 | fprintf(stderr,"\n ERROR could not load image data\n\n"); 153 | return -1; 154 | } 155 | 156 | std::vector outPoints; 157 | calcOuterPoints(id, outPoints, threshold); 158 | 159 | if(outPoints.size() == 0) 160 | { 161 | fprintf(stderr,"\n ERROR no points returned from calculation of outer points?!?!\n\n"); 162 | return -1; 163 | } 164 | 165 | std::vector pts = convex_hull(outPoints); 166 | 167 | if(pts.size() == 0) 168 | { 169 | fprintf(stderr,"\n ERROR no points returned from convex hull creation?!?!\n\n"); 170 | return -1; 171 | } 172 | 173 | writeJSON(pFilename,pts); 174 | 175 | 176 | return 0; 177 | } -------------------------------------------------------------------------------- /canvas-pixel-picking/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/core.js: -------------------------------------------------------------------------------- 1 | /*Copyright 2012 Google Inc. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | #limitations under the License.*/ 14 | 15 | function checkWait(conditionFunction, resultFunction) 16 | { 17 | var tev = setInterval(function() 18 | { 19 | if(conditionFunction()) 20 | { 21 | resultFunction(); 22 | clearInterval(tev) 23 | } 24 | }, 1000); 25 | } 26 | merge = function(original, extended) 27 | { 28 | for (var key in extended) 29 | { 30 | var ext = extended[key]; 31 | if ( 32 | typeof (ext) != 'object' || 33 | ext instanceof Class 34 | ) 35 | { 36 | original[key] = ext; 37 | } 38 | else 39 | { 40 | if (!original[key] || typeof (original[key]) != 'object') 41 | { 42 | original[key] = {}; 43 | } 44 | merge(original[key], ext); 45 | } 46 | } 47 | return original; 48 | }; 49 | 50 | function copy(object) 51 | { 52 | if ( 53 | !object || typeof (object) != 'object' || 54 | object instanceof Class 55 | ) { 56 | return object; 57 | } 58 | else if (object instanceof Array) { 59 | var c = []; 60 | for (var i = 0, l = object.length; i < l; i++) { 61 | c[i] = copy(object[i]); 62 | } 63 | return c; 64 | } 65 | else { 66 | var c = {}; 67 | for (var i in object) { 68 | c[i] = copy(object[i]); 69 | } 70 | return c; 71 | } 72 | }; 73 | 74 | function ksort(obj) { 75 | if (!obj || typeof (obj) != 'object') { 76 | return []; 77 | } 78 | 79 | var keys = [], values = []; 80 | for (var i in obj) { 81 | keys.push(i); 82 | } 83 | 84 | keys.sort(); 85 | for (var i = 0; i < keys.length; i++) { 86 | values.push(obj[keys[i]]); 87 | } 88 | 89 | return values; 90 | }; 91 | 92 | // ----------------------------------------------------------------------------- 93 | // Class object based on John Resigs code; inspired by base2 and Prototype 94 | // http://ejohn.org/blog/simple-javascript-inheritance/ 95 | (function(){ 96 | var initializing = false, fnTest = /xyz/.test(function() { xyz; }) ? /\bparent\b/ : /.*/; 97 | 98 | this.Class = function() { }; 99 | var inject = function(prop) 100 | { 101 | var proto = this.prototype; 102 | var parent = {}; 103 | for (var name in prop) 104 | { 105 | if ( 106 | typeof (prop[name]) == "function" && 107 | typeof (proto[name]) == "function" && 108 | fnTest.test(prop[name]) 109 | ) 110 | { 111 | parent[name] = proto[name]; // save original function 112 | proto[name] = (function(name, fn) 113 | { 114 | return function() 115 | { 116 | var tmp = this.parent; 117 | this.parent = parent[name]; 118 | var ret = fn.apply(this, arguments); 119 | this.parent = tmp; 120 | return ret; 121 | }; 122 | })(name, prop[name]) 123 | } 124 | else 125 | { 126 | proto[name] = prop[name]; 127 | } 128 | } 129 | }; 130 | 131 | this.Class.extend = function(prop) 132 | { 133 | var parent = this.prototype; 134 | 135 | initializing = true; 136 | var prototype = new this(); 137 | initializing = false; 138 | 139 | for (var name in prop) 140 | { 141 | if ( 142 | typeof (prop[name]) == "function" && 143 | typeof (parent[name]) == "function" && 144 | fnTest.test(prop[name]) 145 | ) 146 | { 147 | prototype[name] = (function(name, fn) 148 | { 149 | return function() 150 | { 151 | var tmp = this.parent; 152 | this.parent = parent[name]; 153 | var ret = fn.apply(this, arguments); 154 | this.parent = tmp; 155 | return ret; 156 | }; 157 | })(name, prop[name]) 158 | } 159 | else 160 | { 161 | prototype[name] = prop[name]; 162 | } 163 | } 164 | 165 | function Class() 166 | { 167 | if (!initializing) 168 | { 169 | 170 | // If this class has a staticInstantiate method, invoke it 171 | // and check if we got something back. If not, the normal 172 | // constructor (init) is called. 173 | if (this.staticInstantiate) 174 | { 175 | var obj = this.staticInstantiate.apply(this, arguments); 176 | if (obj) 177 | { 178 | return obj; 179 | } 180 | } 181 | 182 | for (var p in this) 183 | { 184 | if (typeof (this[p]) == 'object') 185 | { 186 | this[p] = copy(this[p]); // deep copy! 187 | } 188 | } 189 | 190 | if (this.init) 191 | { 192 | this.init.apply(this, arguments); 193 | } 194 | } 195 | return this; 196 | } 197 | 198 | Class.prototype = prototype; 199 | Class.constructor = Class; 200 | Class.extend = arguments.callee; 201 | Class.inject = inject; 202 | 203 | return Class; 204 | }; 205 | })(); 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/1_grits_tiling/TILEDmap.js: -------------------------------------------------------------------------------- 1 | 2 | var CanvasTile = Class.extend({ 3 | x:0, 4 | y:0, 5 | w:100, 6 | h:100, 7 | cvsHdl:null, 8 | ctx:null, 9 | 10 | //----------------------------- 11 | create:function(width,height) 12 | { 13 | this.x = -1; 14 | this.y = -1; 15 | this.w = width; 16 | this.h = height; 17 | var can2 = document.createElement('canvas'); 18 | can2.width = width; 19 | can2.height = height; 20 | this.cvsHdl = can2; 21 | this.ctx = can2.getContext('2d'); 22 | 23 | 24 | }, 25 | //----------------------------- 26 | isVisible:function() 27 | { 28 | var r2 = gMap.viewRect; 29 | var r1 = this; 30 | return gMap.intersectRect( {top:r1.y, 31 | left:r1.x, 32 | bottom:r1.y+r1.h, 33 | right:r1.x+r1.w}, 34 | {top:r2.y, 35 | left:r2.x, 36 | bottom:r2.y+r2.h, 37 | right:r2.x+r2.w}); 38 | 39 | 40 | } 41 | 42 | }); 43 | 44 | var TILEDmap = Class.extend({ 45 | currMapData: null, 46 | tileSets: new Array(), 47 | viewRect: { 48 | "x": 0, 49 | "y": 0, 50 | "w": 1000, 51 | "h": 1000 52 | }, 53 | numXTiles: 100, 54 | numYTiles: 100, 55 | tileSize: { 56 | "x": 64, 57 | "y": 64 58 | }, 59 | pixelSize: { 60 | "x": 64, 61 | "y": 64 62 | }, 63 | 64 | imgLoadCount:0, 65 | fullyLoaded:false, 66 | canvasTileSize:{"x":1024,"y":1024}, 67 | canvasTileArray:[], 68 | //--------------------------- 69 | load: function (map) 70 | { 71 | 72 | xhrGet(map, false,function(data) 73 | { 74 | gMap.parseMapJSON(data.response); 75 | 76 | }); 77 | }, 78 | //--------------------------- 79 | 80 | parseMapJSON:function(mapJSON) 81 | { 82 | this.currMapData = JSON.parse( mapJSON ); 83 | var map = this.currMapData; 84 | this.numXTiles = map.width; 85 | this.numYTiles = map.height; 86 | this.tileSize.x = map.tilewidth; 87 | this.tileSize.y = map.tileheight; 88 | this.pixelSize.x = this.numXTiles * this.tileSize.x; 89 | this.pixelSize.y = this.numYTiles * this.tileSize.y; 90 | 91 | //load our tilesets if we are a client. 92 | var gMap = this; 93 | for (var i = 0; i < map.tilesets.length; i++) 94 | { 95 | var img = new Image(); 96 | img.onload = new function() {gMap.imgLoadCount++;}; 97 | img.src = "../data/" + map.tilesets[i].image.replace(/^.*[\\\/]/, ''); 98 | var ts = { 99 | "firstgid": map.tilesets[i].firstgid, 100 | "image": img, 101 | "imageheight": map.tilesets[i].imageheight, 102 | "imagewidth": map.tilesets[i].imagewidth, 103 | "name": map.tilesets[i].name, 104 | "numXTiles": Math.floor(map.tilesets[i].imagewidth / this.tileSize.x), 105 | "numYTiles": Math.floor(map.tilesets[i].imageheight / this.tileSize.y) 106 | }; 107 | this.tileSets.push(ts); 108 | 109 | 110 | //clm precache the bg 111 | checkWait( 112 | function() 113 | { 114 | return gMap.imgLoadCount == gMap.tileSets.length; 115 | }, 116 | function () 117 | { 118 | 119 | gMap.preDrawCache(); 120 | }); 121 | 122 | } 123 | }, 124 | //--------------------------- 125 | getTilePacket: function (tileIndex) { 126 | var pkt = { 127 | "img": null, 128 | "px": 0, 129 | "py": 0 130 | }; 131 | var i = 0; 132 | for (i = this.tileSets.length - 1; i >= 0; i--) { 133 | if (this.tileSets[i].firstgid <= tileIndex) break; 134 | } 135 | 136 | pkt.img = this.tileSets[i].image; 137 | var localIdx = tileIndex - this.tileSets[i].firstgid; 138 | var lTileX = Math.floor(localIdx % this.tileSets[i].numXTiles); 139 | var lTileY = Math.floor(localIdx / this.tileSets[i].numXTiles); 140 | pkt.px = (lTileX * this.tileSize.x); 141 | pkt.py = (lTileY * this.tileSize.y); 142 | 143 | return pkt; 144 | }, 145 | //--------------------------- 146 | intersectRect:function (r1, r2) 147 | { 148 | return !(r2.left > r1.right || 149 | r2.right < r1.left || 150 | r2.top > r1.bottom || 151 | r2.bottom < r1.top); 152 | }, 153 | //--------------------------- 154 | draw: function (ctx) 155 | { // 156 | if(!this.fullyLoaded) return; 157 | 158 | //aabb test to see if our view-rect intersects with this canvas. 159 | for(var q =0; q < this.canvasTileArray.length; q++) 160 | { 161 | var r1 = this.canvasTileArray[q]; 162 | 163 | if(r1.isVisible()) 164 | ctx.drawImage(r1.cvsHdl, r1.x-this.viewRect.x,r1.y-this.viewRect.y); 165 | } 166 | }, 167 | //--------------------------- 168 | preDrawCache:function() 169 | { 170 | var xCanvasCount = 1 + Math.floor(this.pixelSize.x / this.canvasTileSize.x); 171 | var yCanvasCount = 1 + Math.floor(this.pixelSize.y / this.canvasTileSize.y); 172 | var numSubCanv = xCanvasCount*yCanvasCount; 173 | 174 | for(var yC = 0; yC 4 | 5 | 6 | -------------------------------------------------------------------------------- /canvas-pixel-picking/core.js: -------------------------------------------------------------------------------- 1 | /*Copyright 2012 Google Inc. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | #limitations under the License.*/ 14 | 15 | 16 | 17 | Number.prototype.map = function(istart, istop, ostart, ostop) { 18 | return ostart + (ostop - ostart) * ((this - istart) / (istop - istart)); 19 | }; 20 | 21 | Number.prototype.limit = function(min, max) { 22 | return Math.min(max, Math.max(min, this)); 23 | }; 24 | 25 | Number.prototype.round = function(precision) { 26 | precision = Math.pow(10, precision || 0); 27 | return Math.round(this * precision) / precision; 28 | }; 29 | 30 | Number.prototype.floor = function() { 31 | return Math.floor(this); 32 | }; 33 | 34 | Number.prototype.ceil = function() { 35 | return Math.ceil(this); 36 | }; 37 | 38 | Number.prototype.toInt = function() { 39 | return (this | 0); 40 | }; 41 | 42 | Array.prototype.erase = function(item) { 43 | for (var i = this.length; i--; i) { 44 | if (this[i] === item) this.splice(i, 1); 45 | } 46 | return this; 47 | }; 48 | 49 | Array.prototype.random = function() { 50 | return this[ (Math.random() * this.length).floor() ]; 51 | }; 52 | 53 | Function.prototype.bind = function(bind) { 54 | var self = this; 55 | return function(){ 56 | var args = Array.prototype.slice.call(arguments); 57 | return self.apply(bind || null, args); 58 | }; 59 | }; 60 | 61 | merge = function(original, extended) 62 | { 63 | for (var key in extended) 64 | { 65 | var ext = extended[key]; 66 | if ( 67 | typeof (ext) != 'object' || 68 | ext instanceof Class 69 | ) 70 | { 71 | original[key] = ext; 72 | } 73 | else 74 | { 75 | if (!original[key] || typeof (original[key]) != 'object') 76 | { 77 | original[key] = {}; 78 | } 79 | merge(original[key], ext); 80 | } 81 | } 82 | return original; 83 | }; 84 | 85 | function copy(object) 86 | { 87 | if ( 88 | !object || typeof (object) != 'object' || 89 | object instanceof Class 90 | ) { 91 | return object; 92 | } 93 | else if (object instanceof Array) { 94 | var c = []; 95 | for (var i = 0, l = object.length; i < l; i++) { 96 | c[i] = copy(object[i]); 97 | } 98 | return c; 99 | } 100 | else { 101 | var c = {}; 102 | for (var i in object) { 103 | c[i] = copy(object[i]); 104 | } 105 | return c; 106 | } 107 | }; 108 | 109 | function ksort(obj) { 110 | if (!obj || typeof (obj) != 'object') { 111 | return []; 112 | } 113 | 114 | var keys = [], values = []; 115 | for (var i in obj) { 116 | keys.push(i); 117 | } 118 | 119 | keys.sort(); 120 | for (var i = 0; i < keys.length; i++) { 121 | values.push(obj[keys[i]]); 122 | } 123 | 124 | return values; 125 | }; 126 | 127 | // ----------------------------------------------------------------------------- 128 | // Class object based on John Resigs code; inspired by base2 and Prototype 129 | // http://ejohn.org/blog/simple-javascript-inheritance/ 130 | (function(){ 131 | var initializing = false, fnTest = /xyz/.test(function() { xyz; }) ? /\bparent\b/ : /.*/; 132 | 133 | this.Class = function() { }; 134 | var inject = function(prop) 135 | { 136 | var proto = this.prototype; 137 | var parent = {}; 138 | for (var name in prop) 139 | { 140 | if ( 141 | typeof (prop[name]) == "function" && 142 | typeof (proto[name]) == "function" && 143 | fnTest.test(prop[name]) 144 | ) 145 | { 146 | parent[name] = proto[name]; // save original function 147 | proto[name] = (function(name, fn) 148 | { 149 | return function() 150 | { 151 | var tmp = this.parent; 152 | this.parent = parent[name]; 153 | var ret = fn.apply(this, arguments); 154 | this.parent = tmp; 155 | return ret; 156 | }; 157 | })(name, prop[name]) 158 | } 159 | else 160 | { 161 | proto[name] = prop[name]; 162 | } 163 | } 164 | }; 165 | 166 | this.Class.extend = function(prop) 167 | { 168 | var parent = this.prototype; 169 | 170 | initializing = true; 171 | var prototype = new this(); 172 | initializing = false; 173 | 174 | for (var name in prop) 175 | { 176 | if ( 177 | typeof (prop[name]) == "function" && 178 | typeof (parent[name]) == "function" && 179 | fnTest.test(prop[name]) 180 | ) 181 | { 182 | prototype[name] = (function(name, fn) 183 | { 184 | return function() 185 | { 186 | var tmp = this.parent; 187 | this.parent = parent[name]; 188 | var ret = fn.apply(this, arguments); 189 | this.parent = tmp; 190 | return ret; 191 | }; 192 | })(name, prop[name]) 193 | } 194 | else 195 | { 196 | prototype[name] = prop[name]; 197 | } 198 | } 199 | 200 | function Class() 201 | { 202 | if (!initializing) 203 | { 204 | 205 | // If this class has a staticInstantiate method, invoke it 206 | // and check if we got something back. If not, the normal 207 | // constructor (init) is called. 208 | if (this.staticInstantiate) 209 | { 210 | var obj = this.staticInstantiate.apply(this, arguments); 211 | if (obj) 212 | { 213 | return obj; 214 | } 215 | } 216 | 217 | for (var p in this) 218 | { 219 | if (typeof (this[p]) == 'object') 220 | { 221 | this[p] = copy(this[p]); // deep copy! 222 | } 223 | } 224 | 225 | if (this.init) 226 | { 227 | this.init.apply(this, arguments); 228 | } 229 | } 230 | return this; 231 | } 232 | 233 | Class.prototype = prototype; 234 | Class.constructor = Class; 235 | Class.extend = arguments.callee; 236 | Class.inject = inject; 237 | 238 | return Class; 239 | }; 240 | })(); 241 | 242 | 243 | 244 | 245 | newGuid_short = function() 246 | { 247 | var S4 = function() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); }; 248 | return (S4()).toString(); 249 | }; 250 | 251 | newGuid = function() 252 | { 253 | var S4 = function() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); }; 254 | return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()).toString(); 255 | }; 256 | 257 | 258 | 259 | 260 | XHR = function(domainURL, callerInstance, function_name,opt_argv) 261 | { 262 | 263 | // If optional arguments was not provided, create it as empty 264 | if (!opt_argv) 265 | opt_argv = new Array(); 266 | 267 | // Find if the last arg is a callback function; save it 268 | var callback = null; 269 | var len = opt_argv.length; 270 | if (len > 0 && typeof opt_argv[len-1] == 'function') { 271 | callback = opt_argv[len-1]; 272 | opt_argv.length--; 273 | } 274 | var async = (callback != null); 275 | 276 | // Encode the arguments in to a URI 277 | var query = 'fcn=' + encodeURIComponent(function_name); 278 | for (var i = 0; i < opt_argv.length-1; i+=2) { 279 | var key = (opt_argv[i]); 280 | var val = (opt_argv[i + 1]);//JSON.stringify(..) 281 | query += '&' + key + '=' + encodeURIComponent(val); 282 | } 283 | // query += '&time=' + new Date().getTime(); // IE cache workaround 284 | 285 | //query = "fcn=getActiveGames&p0guid=000"; 286 | // See http://en.wikipedia.org/wiki/XMLHttpRequest to make this cross-browser compatible 287 | var req = new XMLHttpRequest(); 288 | 289 | // Create a 'GET' request w/ an optional callback handler 290 | req.open('GET', 'http://localhost:8080/grits/?' + query, async); 291 | 292 | if (async) { 293 | req.onreadystatechange = function() { 294 | if(req.readyState == 4 && req.status == 200) { 295 | var response = null; 296 | try { 297 | response = JSON.parse(req.responseText); 298 | } catch (e) { 299 | response = req.responseText; 300 | } 301 | callback(response); 302 | } 303 | } 304 | } 305 | 306 | // Make the actual request 307 | req.send(null); 308 | 309 | 310 | 311 | }; 312 | -------------------------------------------------------------------------------- /canvas-faster-picking/client/core.js: -------------------------------------------------------------------------------- 1 | /*Copyright 2012 Google Inc. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | #limitations under the License.*/ 14 | 15 | 16 | 17 | Number.prototype.map = function(istart, istop, ostart, ostop) { 18 | return ostart + (ostop - ostart) * ((this - istart) / (istop - istart)); 19 | }; 20 | 21 | Number.prototype.limit = function(min, max) { 22 | return Math.min(max, Math.max(min, this)); 23 | }; 24 | 25 | Number.prototype.round = function(precision) { 26 | precision = Math.pow(10, precision || 0); 27 | return Math.round(this * precision) / precision; 28 | }; 29 | 30 | Number.prototype.floor = function() { 31 | return Math.floor(this); 32 | }; 33 | 34 | Number.prototype.ceil = function() { 35 | return Math.ceil(this); 36 | }; 37 | 38 | Number.prototype.toInt = function() { 39 | return (this | 0); 40 | }; 41 | 42 | Array.prototype.erase = function(item) { 43 | for (var i = this.length; i--; i) { 44 | if (this[i] === item) this.splice(i, 1); 45 | } 46 | return this; 47 | }; 48 | 49 | Array.prototype.random = function() { 50 | return this[ (Math.random() * this.length).floor() ]; 51 | }; 52 | 53 | Function.prototype.bind = function(bind) { 54 | var self = this; 55 | return function(){ 56 | var args = Array.prototype.slice.call(arguments); 57 | return self.apply(bind || null, args); 58 | }; 59 | }; 60 | 61 | merge = function(original, extended) 62 | { 63 | for (var key in extended) 64 | { 65 | var ext = extended[key]; 66 | if ( 67 | typeof (ext) != 'object' || 68 | ext instanceof Class 69 | ) 70 | { 71 | original[key] = ext; 72 | } 73 | else 74 | { 75 | if (!original[key] || typeof (original[key]) != 'object') 76 | { 77 | original[key] = {}; 78 | } 79 | merge(original[key], ext); 80 | } 81 | } 82 | return original; 83 | }; 84 | 85 | function copy(object) 86 | { 87 | if ( 88 | !object || typeof (object) != 'object' || 89 | object instanceof Class 90 | ) { 91 | return object; 92 | } 93 | else if (object instanceof Array) { 94 | var c = []; 95 | for (var i = 0, l = object.length; i < l; i++) { 96 | c[i] = copy(object[i]); 97 | } 98 | return c; 99 | } 100 | else { 101 | var c = {}; 102 | for (var i in object) { 103 | c[i] = copy(object[i]); 104 | } 105 | return c; 106 | } 107 | }; 108 | 109 | function ksort(obj) { 110 | if (!obj || typeof (obj) != 'object') { 111 | return []; 112 | } 113 | 114 | var keys = [], values = []; 115 | for (var i in obj) { 116 | keys.push(i); 117 | } 118 | 119 | keys.sort(); 120 | for (var i = 0; i < keys.length; i++) { 121 | values.push(obj[keys[i]]); 122 | } 123 | 124 | return values; 125 | }; 126 | 127 | // ----------------------------------------------------------------------------- 128 | // Class object based on John Resigs code; inspired by base2 and Prototype 129 | // http://ejohn.org/blog/simple-javascript-inheritance/ 130 | (function(){ 131 | var initializing = false, fnTest = /xyz/.test(function() { xyz; }) ? /\bparent\b/ : /.*/; 132 | 133 | this.Class = function() { }; 134 | var inject = function(prop) 135 | { 136 | var proto = this.prototype; 137 | var parent = {}; 138 | for (var name in prop) 139 | { 140 | if ( 141 | typeof (prop[name]) == "function" && 142 | typeof (proto[name]) == "function" && 143 | fnTest.test(prop[name]) 144 | ) 145 | { 146 | parent[name] = proto[name]; // save original function 147 | proto[name] = (function(name, fn) 148 | { 149 | return function() 150 | { 151 | var tmp = this.parent; 152 | this.parent = parent[name]; 153 | var ret = fn.apply(this, arguments); 154 | this.parent = tmp; 155 | return ret; 156 | }; 157 | })(name, prop[name]) 158 | } 159 | else 160 | { 161 | proto[name] = prop[name]; 162 | } 163 | } 164 | }; 165 | 166 | this.Class.extend = function(prop) 167 | { 168 | var parent = this.prototype; 169 | 170 | initializing = true; 171 | var prototype = new this(); 172 | initializing = false; 173 | 174 | for (var name in prop) 175 | { 176 | if ( 177 | typeof (prop[name]) == "function" && 178 | typeof (parent[name]) == "function" && 179 | fnTest.test(prop[name]) 180 | ) 181 | { 182 | prototype[name] = (function(name, fn) 183 | { 184 | return function() 185 | { 186 | var tmp = this.parent; 187 | this.parent = parent[name]; 188 | var ret = fn.apply(this, arguments); 189 | this.parent = tmp; 190 | return ret; 191 | }; 192 | })(name, prop[name]) 193 | } 194 | else 195 | { 196 | prototype[name] = prop[name]; 197 | } 198 | } 199 | 200 | function Class() 201 | { 202 | if (!initializing) 203 | { 204 | 205 | // If this class has a staticInstantiate method, invoke it 206 | // and check if we got something back. If not, the normal 207 | // constructor (init) is called. 208 | if (this.staticInstantiate) 209 | { 210 | var obj = this.staticInstantiate.apply(this, arguments); 211 | if (obj) 212 | { 213 | return obj; 214 | } 215 | } 216 | 217 | for (var p in this) 218 | { 219 | if (typeof (this[p]) == 'object') 220 | { 221 | this[p] = copy(this[p]); // deep copy! 222 | } 223 | } 224 | 225 | if (this.init) 226 | { 227 | this.init.apply(this, arguments); 228 | } 229 | } 230 | return this; 231 | } 232 | 233 | Class.prototype = prototype; 234 | Class.constructor = Class; 235 | Class.extend = arguments.callee; 236 | Class.inject = inject; 237 | 238 | return Class; 239 | }; 240 | })(); 241 | 242 | 243 | 244 | 245 | newGuid_short = function() 246 | { 247 | var S4 = function() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); }; 248 | return (S4()).toString(); 249 | }; 250 | 251 | newGuid = function() 252 | { 253 | var S4 = function() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); }; 254 | return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()).toString(); 255 | }; 256 | 257 | 258 | 259 | 260 | XHR = function(domainURL, callerInstance, function_name,opt_argv) 261 | { 262 | 263 | // If optional arguments was not provided, create it as empty 264 | if (!opt_argv) 265 | opt_argv = new Array(); 266 | 267 | // Find if the last arg is a callback function; save it 268 | var callback = null; 269 | var len = opt_argv.length; 270 | if (len > 0 && typeof opt_argv[len-1] == 'function') { 271 | callback = opt_argv[len-1]; 272 | opt_argv.length--; 273 | } 274 | var async = (callback != null); 275 | 276 | // Encode the arguments in to a URI 277 | var query = 'fcn=' + encodeURIComponent(function_name); 278 | for (var i = 0; i < opt_argv.length-1; i+=2) { 279 | var key = (opt_argv[i]); 280 | var val = (opt_argv[i + 1]);//JSON.stringify(..) 281 | query += '&' + key + '=' + encodeURIComponent(val); 282 | } 283 | // query += '&time=' + new Date().getTime(); // IE cache workaround 284 | 285 | //query = "fcn=getActiveGames&p0guid=000"; 286 | // See http://en.wikipedia.org/wiki/XMLHttpRequest to make this cross-browser compatible 287 | var req = new XMLHttpRequest(); 288 | 289 | // Create a 'GET' request w/ an optional callback handler 290 | req.open('GET', 'http://localhost:8080/grits/?' + query, async); 291 | 292 | if (async) { 293 | req.onreadystatechange = function() { 294 | if(req.readyState == 4 && req.status == 200) { 295 | var response = null; 296 | try { 297 | response = JSON.parse(req.responseText); 298 | } catch (e) { 299 | response = req.responseText; 300 | } 301 | callback(response); 302 | } 303 | } 304 | } 305 | 306 | // Make the actual request 307 | req.send(null); 308 | 309 | 310 | 311 | }; 312 | -------------------------------------------------------------------------------- /needle.js/needle.js: -------------------------------------------------------------------------------- 1 | /*Copyright 2013 Google Inc. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | #limitations under the License.*/ 14 | 15 | /* 16 | Needle.js is a javascript inline-profiling library which aims to add the least amount of memory and runtime overhead possible. Right now we have a ~0.0001ms - 0.0004ms overhead per event; 17 | For example, 10,000 begin/end blocks adds about ~2.6ms - 7ms overhead to your frame. 18 | See github.com/mainroach for more. 19 | */ 20 | 21 | 22 | var needle={ 23 | mBatchIndex : 0, //what's our current batch 24 | mCurrBatch : null, 25 | mArraySize : 2048, //the size of our bucket of samples 26 | mArrayIndex : 0, //counter in this bucket 27 | 28 | mBatches:[], 29 | 30 | mIsHighPrecision:false, 31 | 32 | init:function(preAllocSamples, isHighPrecision) 33 | { 34 | this.mIsHighPrecision = isHighPrecision; 35 | this.mBatchIndex = 0; 36 | this.mArrayIndex = 0; 37 | 38 | this.mBatches.length = 0; 39 | 40 | var numBatches = preAllocSamples / this.mArraySize; 41 | 42 | for(var i =0; i < numBatches; i++) 43 | this.addBatch(); 44 | 45 | this.mCurrBatch = this.mBatches[0]; 46 | }, 47 | 48 | 49 | // Add a batch, mostly internal only... 50 | addBatch:function() 51 | { 52 | var btc = {}; 53 | btc.mSamType = new Array(this.mArraySize);//Uint8Array(this.mArraySize); 54 | btc.mSamName = new Array(this.mArraySize); 55 | btc.mSamTime = new Array(this.mArraySize);//Float64Array(this.mArraySize); 56 | 57 | 58 | 59 | this.mCurrBatch = btc; 60 | this.mBatches.push(btc); 61 | }, 62 | 63 | 64 | // Called at the start of a scope, returns < 1ms precision 65 | _beginFine:function(name) 66 | { 67 | var btch = this.mCurrBatch; 68 | 69 | btch.mSamType[this.mArrayIndex] = 1; 70 | btch.mSamName[this.mArrayIndex] = name; 71 | btch.mSamTime[this.mArrayIndex] = window.performance.now(); 72 | 73 | this.mArrayIndex++; 74 | if(this.mArrayIndex >= this.mArraySize) 75 | { 76 | if(this.mBatchIndex >= this.mBatches.length-1) 77 | { 78 | this.addBatch(); 79 | this.mBatchIndex = this.mBatches.length-1; 80 | } 81 | else 82 | { 83 | this.mBatchIndex++; 84 | this.mCurrBatch = this.mBatches[this.mBatchIndex]; 85 | } 86 | this.mArrayIndex = 0; 87 | } 88 | }, 89 | 90 | // Called at the end of a scope, returns < 1ms precision 91 | _endFine:function() 92 | { 93 | var btch = this.mCurrBatch; 94 | 95 | btch.mSamType[this.mArrayIndex] = 2; 96 | btch.mSamTime[this.mArrayIndex] = window.performance.now(); 97 | 98 | this.mArrayIndex++; 99 | if(this.mArrayIndex >= this.mArraySize) 100 | { 101 | if(this.mBatchIndex >= this.mBatches.length-1) 102 | { 103 | this.addBatch(); 104 | this.mBatchIndex = this.mBatches.length-1; 105 | } 106 | else 107 | { 108 | this.mBatchIndex++; 109 | this.mCurrBatch = this.mBatches[this.mBatchIndex]; 110 | } 111 | this.mArrayIndex = 0; 112 | } 113 | }, 114 | 115 | // Called at the start of a scope, returns 1ms precision 116 | _beginCoarse:function(name) 117 | { 118 | var btch = this.mCurrBatch; 119 | 120 | btch.mSamType[this.mArrayIndex] = 1; 121 | btch.mSamName[this.mArrayIndex] = name; 122 | btch.mSamTime[this.mArrayIndex] = Date.now(); 123 | 124 | this.mArrayIndex++; 125 | if(this.mArrayIndex >= this.mArraySize) 126 | { 127 | if(this.mBatchIndex >= this.mBatches.length-1) 128 | { 129 | this.addBatch(); 130 | this.mBatchIndex = this.mBatches.length-1; 131 | } 132 | else 133 | { 134 | this.mBatchIndex++; 135 | this.mCurrBatch = this.mBatches[this.mBatchIndex]; 136 | } 137 | this.mArrayIndex = 0; 138 | } 139 | }, 140 | 141 | // Called at the end of a scope, returns 1ms precision. 142 | _endCoarse:function() 143 | { 144 | var btch = this.mCurrBatch; 145 | 146 | btch.mSamType[this.mArrayIndex] = 2; 147 | btch.mSamTime[this.mArrayIndex] = Date.now(); 148 | 149 | this.mArrayIndex++; 150 | if(this.mArrayIndex >= this.mArraySize) 151 | { 152 | if(this.mBatchIndex >= this.mBatches.length-1) 153 | { 154 | this.addBatch(); 155 | this.mBatchIndex = this.mBatches.length-1; 156 | } 157 | else 158 | { 159 | this.mBatchIndex++; 160 | this.mCurrBatch = this.mBatches[this.mBatchIndex]; 161 | } 162 | this.mArrayIndex = 0; 163 | } 164 | }, 165 | 166 | // public accessors - we use vtable swaps rather than enabled/disabled flags 167 | begin : function(name){}, 168 | end : function(){}, 169 | 170 | // needle is disabled by default, call this function to 171 | enable:function() 172 | { 173 | if(!this.mIsHighPrecision) 174 | { 175 | this.begin = this._beginCoarse; 176 | this.end = this._endCoarse; 177 | } 178 | else 179 | { 180 | this.begin = this._beginFine; 181 | this.end = this._endFine; 182 | } 183 | }, 184 | 185 | // once you've added needle sampling code all over your codebase, you can null it's influence out via calling needle.makeBlunt 186 | // this will stub out the begin/end functions so that you don't incur overhead 187 | disable:function() 188 | { 189 | this.begin = function(name){}; 190 | this.end = function(){}; 191 | }, 192 | 193 | 194 | }; 195 | 196 | // Call this at the end of sampling to get a list of all samples in a usable form 197 | // don't expect this to be fast; Only call at the end of profiling. 198 | needle.getExportReadyData =function() 199 | { 200 | var oneArray = new Array(); 201 | for (var q =0; q < this.mBatchIndex; q++) 202 | { 203 | var bkt = this.mBatches[q]; 204 | for(var i =0; i < this.mArraySize; i++) 205 | { 206 | if(bkt.mSamType[i] == 0) 207 | continue; 208 | var evt = { 209 | type:bkt.mSamType[i], 210 | name:bkt.mSamName[i], 211 | time:bkt.mSamTime[i] 212 | }; 213 | oneArray.push(evt); 214 | } 215 | } 216 | 217 | var bkt = this.mBatches[this.mBatchIndex]; 218 | for(var i =0; i < this.mArrayIndex; i++) 219 | { 220 | if(bkt.mSamType[i] == 0) 221 | continue; 222 | var evt = { 223 | type:bkt.mSamType[i], 224 | name:bkt.mSamName[i], 225 | time:bkt.mSamTime[i] 226 | }; 227 | oneArray.push(evt); 228 | } 229 | 230 | return oneArray; 231 | }; 232 | 233 | // Right now simply dumps linear results out to console; should do something smarter with outputing a about:tracing layout. 234 | needle.consolePrint = function(samples) 235 | { 236 | var stack = new Array(); 237 | for (var q =0; q < samples.length; q++) 238 | { 239 | var evt = samples[q]; 240 | if(evt.type == 1) 241 | { 242 | stack.push(evt); 243 | } 244 | else if(evt.type == 2) 245 | { 246 | var lastEvt = stack.pop(); 247 | var delta = (evt.time - lastEvt.time ) ; 248 | 249 | console.log(lastEvt.name + ": " + delta + "ms"); 250 | } 251 | } 252 | }; 253 | 254 | 255 | needle.tracingPrint = function(samples) 256 | { 257 | var traceString = "["; 258 | var traceEventGen = function(name,time,isStart){ 259 | var evt = {name:name,pid:42,tid:"0xBEEF",ts:time,ph:"B"}; 260 | if(!isStart) 261 | evt.ph = "E" 262 | return JSON.stringify(evt); 263 | }; 264 | 265 | var stack = new Array(); 266 | for (var q =0; q < samples.length; q++) 267 | { 268 | var evt = samples[q]; 269 | if(evt.type == 1) 270 | { 271 | stack.push(evt.name); 272 | traceString += traceEventGen(evt.name,evt.time,true) + ",\n"; 273 | } 274 | else if(evt.type == 2) 275 | { 276 | var nm = stack.pop(); 277 | traceString += traceEventGen(nm,evt.time,false) + ",\n"; 278 | } 279 | } 280 | 281 | traceString += "{}]"; 282 | return traceString; 283 | } 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/2_refresh_tiling/TILEDmap.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var CanvasTile = Class.extend({ 4 | x:0, 5 | y:0, 6 | w:100, 7 | h:100, 8 | cvsHdl:null, 9 | ctx:null, 10 | isFree:true, 11 | numFramesNoVisible:0, 12 | //----------------------------- 13 | create:function(width,height) 14 | { 15 | this.x = -1; 16 | this.y = -1; 17 | this.w = width; 18 | this.h = height; 19 | var can2 = document.createElement('canvas'); 20 | can2.width = width; 21 | can2.height = height; 22 | this.cvsHdl = can2; 23 | this.ctx = can2.getContext('2d'); 24 | 25 | this.isFree = true; 26 | }, 27 | //----------------------------- 28 | update:function() 29 | { 30 | if(this.isFree) return; 31 | 32 | 33 | //if i'm not visible, age me 34 | if(!this.isVisible()) 35 | { 36 | this.numFramesNoVisible++; 37 | 38 | if(this.numFramesNoVisible > 100) //promote to freed 39 | { 40 | this.isFree=true; 41 | this.x = -1; 42 | this.y = -1; 43 | } 44 | } 45 | }, 46 | //----------------------------- 47 | isVisible:function() 48 | { 49 | var r2 = gMap.viewRect; 50 | var r1 = this; 51 | return gMap.intersectRect( {top:r1.y, 52 | left:r1.x, 53 | bottom:r1.y+r1.h, 54 | right:r1.x+r1.w}, 55 | {top:r2.y, 56 | left:r2.x, 57 | bottom:r2.y+r2.h, 58 | right:r2.x+r2.w}); 59 | 60 | 61 | }, 62 | //----------------------------- 63 | doesMatchRect:function(x,y,w,h) 64 | { 65 | return (this.x == x && this.y ==y && this.w == w && this.h==h); 66 | } 67 | 68 | 69 | }); 70 | 71 | var TILEDmap = Class.extend({ 72 | currMapData: null, 73 | tileSets: new Array(), 74 | viewRect: { 75 | "x": 0, 76 | "y": 0, 77 | "w": 1000, 78 | "h": 1000 79 | }, 80 | numXTiles: 100, 81 | numYTiles: 100, 82 | tileSize: { 83 | "x": 64, 84 | "y": 64 85 | }, 86 | pixelSize: { 87 | "x": 64, 88 | "y": 64 89 | }, 90 | tileImg:null, 91 | imgLoadCount:0, 92 | fullyLoaded:false, 93 | 94 | numCanvases:30, 95 | canvasTileSize:{"x":512,"y":512}, 96 | canvasTileArray:[], 97 | //--------------------------- 98 | load: function (map) 99 | { 100 | xhrGet(map, false,function(data) 101 | { 102 | gMap.parseMapJSON(data.response); 103 | 104 | }); 105 | //generate our canvas freelist 106 | for(var i =0; i < this.numCanvases; i++) 107 | { 108 | var k = new CanvasTile(); 109 | k.create(this.canvasTileSize.x,this.canvasTileSize.y); 110 | this.canvasTileArray.push(k); 111 | } 112 | }, 113 | //--------------------------- 114 | fetchFreeCanvas:function() 115 | { 116 | //do we have a free canvas? 117 | for(var i =0; i < this.canvasTileArray.length; i++) 118 | { 119 | if(this.canvasTileArray[i].isFree) 120 | { 121 | this.canvasTileArray[i].isFree = false; 122 | return this.canvasTileArray[i]; 123 | } 124 | } 125 | 126 | //no free canvas yet, find one of the used canvases.. 127 | //pick the one with the higest 128 | var oldest = 0; 129 | var winner = null; 130 | for(var i =0; i < this.canvasTileArray.length; i++) 131 | { 132 | if(this.canvasTileArray[i].isFree) continue; 133 | if(this.canvasTileArray[i].numFramesNoVisible > oldest) 134 | { 135 | oldest = this.canvasTileArray[i].numFramesNoVisible; 136 | winner = this.canvasTileArray[i]; 137 | } 138 | 139 | } 140 | winner.isFree = false; 141 | return winner; 142 | }, 143 | //--------------------------- 144 | 145 | parseMapJSON:function(mapJSON) 146 | { 147 | this.currMapData = JSON.parse( mapJSON ); 148 | var map = this.currMapData; 149 | this.numXTiles = map.width; 150 | this.numYTiles = map.height; 151 | this.tileSize.x = map.tilewidth; 152 | this.tileSize.y = map.tileheight; 153 | this.pixelSize.x = this.numXTiles * this.tileSize.x; 154 | this.pixelSize.y = this.numYTiles * this.tileSize.y; 155 | 156 | //load our tilesets if we are a client. 157 | var gMap = this; 158 | for (var i = 0; i < map.tilesets.length; i++) 159 | { 160 | var img = new Image(); 161 | img.onload = new function() {gMap.imgLoadCount++;}; 162 | img.src = "../data/" + map.tilesets[i].image.replace(/^.*[\\\/]/, ''); 163 | var ts = { 164 | "firstgid": map.tilesets[i].firstgid, 165 | "image": img, 166 | "imageheight": map.tilesets[i].imageheight, 167 | "imagewidth": map.tilesets[i].imagewidth, 168 | "name": map.tilesets[i].name, 169 | "numXTiles": Math.floor(map.tilesets[i].imagewidth / this.tileSize.x), 170 | "numYTiles": Math.floor(map.tilesets[i].imageheight / this.tileSize.y) 171 | }; 172 | this.tileSets.push(ts); 173 | 174 | 175 | //clm precache the bg 176 | checkWait( 177 | function() 178 | { 179 | return gMap.imgLoadCount == gMap.tileSets.length; 180 | }, 181 | function () 182 | { 183 | 184 | gMap.fullyLoaded = true; 185 | }); 186 | 187 | } 188 | }, 189 | 190 | //--------------------------- 191 | getTilePacket: function (tileIndex) { 192 | var pkt = { 193 | "img": null, 194 | "px": 0, 195 | "py": 0 196 | }; 197 | var i = 0; 198 | for (i = this.tileSets.length - 1; i >= 0; i--) { 199 | if (this.tileSets[i].firstgid <= tileIndex) break; 200 | } 201 | 202 | pkt.img = this.tileSets[i].image; 203 | var localIdx = tileIndex - this.tileSets[i].firstgid; 204 | var lTileX = Math.floor(localIdx % this.tileSets[i].numXTiles); 205 | var lTileY = Math.floor(localIdx / this.tileSets[i].numXTiles); 206 | pkt.px = (lTileX * this.tileSize.x); 207 | pkt.py = (lTileY * this.tileSize.y); 208 | 209 | return pkt; 210 | }, 211 | //--------------------------- 212 | intersectRect:function (r1, r2) { 213 | return !(r2.left > r1.right || 214 | r2.right < r1.left || 215 | r2.top > r1.bottom || 216 | r2.bottom < r1.top); 217 | }, 218 | //--------------------------- 219 | draw: function (ctx) 220 | { // 221 | if(!this.fullyLoaded) return; 222 | 223 | //do an update of our canvas arrays 224 | for(var i =0; i < this.canvasTileArray.length; i++) 225 | this.canvasTileArray[i].update(); 226 | 227 | //determine what canvasTilings would be visible here, expand our view rect to smooth tiling artifacts.. 228 | 229 | var xTileMin = Math.floor((this.viewRect.x) / this.canvasTileSize.x); 230 | var xTileMax = Math.floor((this.viewRect.x+this.viewRect.w) / this.canvasTileSize.x); 231 | var yTileMin = Math.floor((this.viewRect.y) / this.canvasTileSize.y); 232 | var yTileMax = Math.floor((this.viewRect.y+this.viewRect.h) / this.canvasTileSize.y); 233 | 234 | if(xTileMin <0) xTileMin=0; 235 | if(yTileMin <0) yTileMin=0; 236 | var visibles=[]; 237 | for(var yC = yTileMin; yC <=yTileMax; yC ++) 238 | { 239 | for(var xC = xTileMin; xC <=xTileMax; xC ++) 240 | { 241 | var rk = { 242 | x:xC * this.canvasTileSize.x, 243 | y:yC * this.canvasTileSize.y, 244 | w:this.canvasTileSize.x, 245 | h:this.canvasTileSize.y 246 | }; 247 | 248 | var found = false; 249 | for(var i =0; i < this.canvasTileArray.length; i++) 250 | { 251 | if(this.canvasTileArray[i].doesMatchRect(rk.x,rk.y,rk.w,rk.h)) 252 | { 253 | found = true; 254 | visibles.push(this.canvasTileArray[i]); 255 | } 256 | } 257 | 258 | if(found) continue; 259 | 260 | 261 | var cv = this.fetchFreeCanvas(); 262 | cv.x = rk.x; 263 | cv.y = rk.y; 264 | this.fillCanvasTile(cv); 265 | visibles.push(cv); 266 | } 267 | } 268 | 269 | 270 | 271 | var r2 = this.viewRect; 272 | //aabb test to see if our view-rect intersects with this canvas. 273 | for(var q =0; q < visibles.length; q++) 274 | { 275 | var r1 = visibles[q]; 276 | var visible= this.intersectRect( {top:r1.y,left:r1.x,bottom:r1.y+r1.h,right:r2.x+r2.w}, 277 | {top:r2.y,left:r2.x,bottom:r2.y+r2.h,right:r2.x+r2.w}); 278 | 279 | if(visible) 280 | ctx.drawImage(r1.cvsHdl, r1.x-this.viewRect.x,r1.y-this.viewRect.y); 281 | } 282 | 283 | 284 | }, 285 | fillCanvasTile:function(ctile) 286 | { 287 | var ctx = ctile.ctx; 288 | ctx.fillRect(0,0,ctile.w, ctile.h); 289 | var vRect={ top:ctile.y, 290 | left:ctile.x, 291 | bottom:ctile.y+ctile.h, 292 | right:ctile.x+ctile.w}; 293 | 294 | for (var layerIdx = 0; layerIdx < this.currMapData.layers.length; layerIdx++) 295 | { 296 | if (this.currMapData.layers[layerIdx].type != "tilelayer") continue; 297 | 298 | var dat = this.currMapData.layers[layerIdx].data; 299 | //find what the tileIndexOffset is for this layer 300 | for (var tileIDX = 0; tileIDX < dat.length; tileIDX++) { 301 | var tID = dat[tileIDX]; 302 | if (tID == 0) continue; 303 | 304 | var tPKT = this.getTilePacket(tID); 305 | 306 | //test if this tile is within our world bounds 307 | var worldX = Math.floor(tileIDX % this.numXTiles) * this.tileSize.x; 308 | var worldY = Math.floor(tileIDX / this.numXTiles) * this.tileSize.y; 309 | 310 | var visible= this.intersectRect( vRect, 311 | {top:worldY,left:worldX,bottom:worldY + this.tileSize.y,right:worldX + this.tileSize.x}); 312 | if(!visible) 313 | continue; 314 | 315 | // Nine arguments: the element, source (x,y) coordinates, source width and 316 | // height (for cropping), destination (x,y) coordinates, and destination width 317 | // and height (resize). 318 | // ctx.fillRect(worldX,worldY,this.tileSize.x, this.tileSize.y); 319 | 320 | ctx.drawImage(tPKT.img, 321 | tPKT.px, tPKT.py, 322 | this.tileSize.x, this.tileSize.y, 323 | worldX - vRect.left, 324 | worldY - vRect.top, 325 | this.tileSize.x, this.tileSize.y); 326 | 327 | 328 | 329 | } 330 | } 331 | } 332 | }); 333 | 334 | var gMap = new TILEDmap(); -------------------------------------------------------------------------------- /chrome-event-trace/event_trace_impl.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | 6 | #ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_ 7 | #define BASE_DEBUG_TRACE_EVENT_IMPL_H_ 8 | #pragma once 9 | 10 | //#include "build/build_config.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | //#include "event_trace_impl.h" 19 | //#include "base/callback.h" 20 | //#include "base/hash_tables.h" 21 | //#include "base/memory/ref_counted_memory.h" 22 | //#include "base/observer_list.h" 23 | //#include "base/string_util.h" 24 | //#include "base/synchronization/lock.h" 25 | //#include "base/timer.h" 26 | 27 | // Older style trace macros with explicit id and extra data 28 | // Only these macros result in publishing data to ETW as currently implemented. 29 | #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \ 30 | base::debug::TraceLog::AddTraceEventEtw( \ 31 | TRACE_EVENT_PHASE_BEGIN, \ 32 | name, reinterpret_cast(id), extra) 33 | 34 | #define TRACE_EVENT_END_ETW(name, id, extra) \ 35 | base::debug::TraceLog::AddTraceEventEtw( \ 36 | TRACE_EVENT_PHASE_END, \ 37 | name, reinterpret_cast(id), extra) 38 | 39 | #define TRACE_EVENT_INSTANT_ETW(name, id, extra) \ 40 | base::debug::TraceLog::AddTraceEventEtw( \ 41 | TRACE_EVENT_PHASE_INSTANT, \ 42 | name, reinterpret_cast(id), extra) 43 | 44 | template 45 | struct StaticMemorySingletonTraits; 46 | 47 | namespace event_trace 48 | { 49 | 50 | const int kTraceMaxNumArgs = 2; 51 | 52 | // Output records are "Events" and can be obtained via the 53 | // OutputCallback whenever the tracing system decides to flush. This 54 | // can happen at any time, on any thread, or you can programatically 55 | // force it to happen. 56 | class TraceEvent { 57 | public: 58 | union TraceValue { 59 | bool as_bool; 60 | unsigned long long as_uint; 61 | long long as_int; 62 | double as_double; 63 | const void* as_pointer; 64 | const char* as_string; 65 | }; 66 | 67 | TraceEvent(); 68 | TraceEvent(int thread_id, 69 | event_trace::TimeTicks timestamp, 70 | char phase, 71 | const unsigned char* category_enabled, 72 | const char* name, 73 | unsigned long long id, 74 | int num_args, 75 | const char** arg_names, 76 | const unsigned char* arg_types, 77 | const unsigned long long* arg_values, 78 | unsigned char flags); 79 | ~TraceEvent(); 80 | 81 | // Serialize event data to JSON 82 | static void AppendEventsAsJSON(const std::vector& events, 83 | size_t start, 84 | size_t count, 85 | std::string* out); 86 | void AppendAsJSON(std::string* out) const; 87 | 88 | event_trace::TimeTicks timestamp() const { return timestamp_; } 89 | 90 | 91 | const char* name() const { return name_; } 92 | 93 | private: 94 | // Note: these are ordered by size (largest first) for optimal packing. 95 | event_trace::TimeTicks timestamp_; 96 | // id_ can be used to store phase-specific data. 97 | unsigned long long id_; 98 | TraceValue arg_values_[kTraceMaxNumArgs]; 99 | const char* arg_names_[kTraceMaxNumArgs]; 100 | const unsigned char* category_enabled_; 101 | const char* name_; 102 | char* parameter_copy_storage_; 103 | int thread_id_; 104 | char phase_; 105 | unsigned char flags_; 106 | unsigned char arg_types_[kTraceMaxNumArgs]; 107 | }; 108 | 109 | 110 | 111 | 112 | 113 | class TraceLog { 114 | private: 115 | static TraceLog gStaticTraceInstance; 116 | public: 117 | static TraceLog* GetInstance() { return &gStaticTraceInstance;} ; 118 | 119 | // Get set of known categories. This can change as new code paths are reached. 120 | // The known categories are inserted into |categories|. 121 | void GetKnownCategories(std::vector* categories); 122 | 123 | // Enable tracing for provided list of categories. If tracing is already 124 | // enabled, this method does nothing -- changing categories during trace is 125 | // not supported. 126 | // If both included_categories and excluded_categories are empty, 127 | // all categories are traced. 128 | // Else if included_categories is non-empty, only those are traced. 129 | // Else if excluded_categories is non-empty, everything but those are traced. 130 | // Wildcards * and ? are supported (see MatchPattern in string_util.h). 131 | void SetEnabled(const std::vector& included_categories, 132 | const std::vector& excluded_categories); 133 | 134 | // |categories| is a comma-delimited list of category wildcards. 135 | // A category can have an optional '-' prefix to make it an excluded category. 136 | // All the same rules apply above, so for example, having both included and 137 | // excluded categories in the same list would not be supported. 138 | // 139 | // Example: SetEnabled("test_MyTest*"); 140 | // Example: SetEnabled("test_MyTest*,test_OtherStuff"); 141 | // Example: SetEnabled("-excluded_category1,-excluded_category2"); 142 | void SetEnabled(const std::string& categories); 143 | 144 | // Retieves the categories set via a prior call to SetEnabled(). Only 145 | // meaningful if |IsEnabled()| is true. 146 | void GetEnabledTraceCategories(std::vector* included_out, 147 | std::vector* excluded_out); 148 | 149 | // Disable tracing for all categories. 150 | void SetDisabled(); 151 | // Helper method to enable/disable tracing for all categories. 152 | void SetEnabled(bool enabled); 153 | bool IsEnabled() { return enabled_; } 154 | 155 | // Enabled state listeners give a callback when tracing is enabled or 156 | // disabled. This can be used to tie into other library's tracing systems 157 | // on-demand. 158 | class EnabledStateChangedObserver { 159 | public: 160 | // Called just before the tracing system becomes 161 | // enabled. TraceLog::IsEnabled will return false at this point and trace 162 | // macros and methods called within the observer will deadlock. 163 | virtual void OnTraceLogWillEnable() { } 164 | 165 | // Called just before the tracing system disables. TraceLog::IsEnabled is 166 | // still false at this point TRACE macros will still be capturing 167 | // data. However, trace macros and methods called within the observer will 168 | // deadlock. 169 | virtual void OnTraceLogWillDisable() { } 170 | }; 171 | void AddEnabledStateObserver(EnabledStateChangedObserver* listener); 172 | void RemoveEnabledStateObserver(EnabledStateChangedObserver* listener); 173 | 174 | float GetBufferPercentFull() const; 175 | 176 | 177 | 178 | // Flushes all logged data to the callback. 179 | void Flush(); 180 | 181 | // simply annotates the stream with "[" and "]" respectivly 182 | void BeginLogging(); 183 | void EndLogging(); 184 | 185 | // Called by TRACE_EVENT* macros, don't call this directly. 186 | static const unsigned char* GetCategoryEnabled(const char* name); 187 | static const char* GetCategoryName(const unsigned char* category_enabled); 188 | 189 | // Called by TRACE_EVENT* macros, don't call this directly. 190 | // Returns the index in the internal vector of the event if it was added, or 191 | // -1 if the event was not added. 192 | // On end events, the return value of the begin event can be specified along 193 | // with a threshold in microseconds. If the elapsed time between begin and end 194 | // is less than the threshold, the begin/end event pair is dropped. 195 | // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied 196 | // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above. 197 | int AddTraceEvent(char phase, 198 | const unsigned char* category_enabled, 199 | const char* name, 200 | unsigned long long id, 201 | int num_args, 202 | const char** arg_names, 203 | const unsigned char* arg_types, 204 | const unsigned long long* arg_values, 205 | int threshold_begin_id, 206 | long long threshold, 207 | unsigned char flags); 208 | static void AddTraceEventEtw(char phase, 209 | const char* name, 210 | const void* id, 211 | const char* extra); 212 | static void AddTraceEventEtw(char phase, 213 | const char* name, 214 | const void* id, 215 | const std::string& extra); 216 | 217 | int process_id() const { return process_id_; } 218 | 219 | // Exposed for unittesting: 220 | 221 | // Allow tests to inspect TraceEvents. 222 | size_t GetEventsSize() const { return logged_events_.size(); } 223 | const TraceEvent& GetEventAt(size_t index) const { 224 | assert(index < logged_events_.size()); 225 | return logged_events_[index]; 226 | } 227 | 228 | void SetProcessID(int process_id); 229 | 230 | private: 231 | // This allows constructor and destructor to be private and usable only 232 | // by the Singleton class. 233 | friend struct StaticMemorySingletonTraits; 234 | 235 | TraceLog(); 236 | ~TraceLog(); 237 | const unsigned char* GetCategoryEnabledInternal(const char* name); 238 | void AddThreadNameMetadataEvents(); 239 | void AddClockSyncMetadataEvents(); 240 | 241 | // TODO(nduca): switch to per-thread trace buffers to reduce thread 242 | // synchronization. 243 | Lock lock_; 244 | bool enabled_; 245 | std::vector logged_events_; 246 | std::vector included_categories_; 247 | std::vector excluded_categories_; 248 | 249 | std::map thread_names_; 250 | 251 | // XORed with TraceID to make it unlikely to collide with other processes. 252 | unsigned long long process_id_hash_; 253 | 254 | int process_id_; 255 | 256 | //DISALLOW_COPY_AND_ASSIGN(TraceLog); 257 | }; 258 | 259 | } 260 | #endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_ 261 | -------------------------------------------------------------------------------- /canvas_tiled_rendering/data/largeLevel.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | eJztnOtx41oOhAFJVRsHaSeiRyKkmIhsJWJJVRuHH382jk1kxWt8F02OZuy9nhkfeegqlPg8ItFAN3BI2Wz6m/6mv7f+/j3Zp9qER1k24VGWTXiUZRMeZdm14fGfAq5hwuN99hL22dfxlfH4Xj68/MD+yXilWOl4fM9+hMd7sSnRrgWPcVz3vv7v6HPC4/fjoHi8hcUlTCa++jlYXMqPr8hZJePxI/sIHiXnSMl4XPLbpW1TfnwuJuPtb2nJZ9/DV8LjPXYQAwPd9tnX95l43IjNz1afbXa2KpaXZ9vG+lzsJo7zsH65jeMWsX8b2zex3MWYB/sWE5Y9jl/KuKvYtpbv53s81lfxHav4jlqusYvtsziniW1bLw+PRdz7jdzvTdxnF9e+EnwWsd6JT9o4rxMsljIOy22MN8ZDrYrj8R3j38i1rOS6waaK7+JasOVovbbE+VQoHrX4AR9yj+CDb8gH8uY2zp+Lj9axj7Fm4csm/PUjPBQHxsOH/bjkGvHRfz+x0cq1zy3zdyPHcA73XRoeXHdlmSP4fRn3eBu+xP8b8Qvx18Y4W0vecEuumcWxG8u8amL7PL53JmNsZKwm9q/k+zXfuP4qjlvHdnzPse3o+7xAPIiTTny2is9GfFnLJ8vz8Nc67rmOeybPKtm+kLGa2I5OdOE3xkRnyInbMDSFmGd5K8et41zyE65bxvUQS4xZGh7kO583lvrA8sqSp9HJhXzWcY/EXWeZM0v5BBfypInvxU/4iFykJmjC740lr6J1W0u+3cT43A98Sa7CX10cWyJfafwS0zP5XMjybdwPn3DFWF/AAI7p5DuI84UNeQqOITer8PVCsFnI98JpjEeOkiPKo9RcXEtjWZOVhsdcfEyuE1fcLzlA7OJ7akliDb2dW3J+ZxmjMxmD+li5CZ1eyD5yq7PMCa1f0ZLKMk6ILXJ6LWNi5FVpeJAD5DzcA/eSG3A1HIOvVV/haWIajMhBeIw4Z/vWhvHAPtVktAn9QQeqkcFH4EcMqHagb8rH/9R+Nh70TGg1tT/1OjwM38AVK8uYXMm+hZyjOCt21FBaV6MRaBX5CYe5DXuKtWyDI7XOA39yud++Px+4O9udJx/WH7RfgQd+29qQU1RzN5axPtZeOA1fsry1rPtdvsNlP/jjUziKeg+s8DN6Bg8R78QL9e7RX/s98mkp46Nb/f7S8ECPGR9swIWepLEhB5Dvt/KJvzUXqIcYDx934p96NM7GhrFLfVBZahNxQb6tbejv57OvX872eLYnf13vz9H1fv+/Zh+zn43HrdwjOMBF8MHKktfhJ/y3kTGI37kNezDO1foInG4t9ZnxVUPIS7R5a1kDbwTX/rv7eN8GH/Wf3dmas7U/WC8ND/hX9YE6Hh5G9zRnqBvJGeoZfAxvwy34GG5CezRnNpY1qfLLOjCYy3nwZO/7Y8S76sP9O9dLw0N5h9qE+gh+by3jlVpoaVlj4D+tPVUnWss6GNzJK7aTc8qVt3IN6AXadAp9uA9OQi8eznb4P9ZLw4NYxagNVzbMETBZyDHgUlnyO8eSR+TQ0rLHoLZlLLQbU+xqy/6m33YffuyC/3cjPRjrw1vrpeExEx8R3/BXbcMeWTlna6nt8Lf6t5bjVpZ1AXkEr60t84yYaASbxoa8tQtfdqIHu4j7u1g/xTHPV6gf5AEaAC8Qp/gEf4OZ+tMtawI0Q48Fz9uR4XvOpzYjXzgHvUJD7gODsR6A1UP4vLtC/SC24SX4Hj6nX2wt+0OORWvgMnqPzjIHZpbc01r2EtTVlaVOw2/wFedxLeTPywU96CLmT8JLx/D5/RXpB1hQH8FRyj/0hXBKbVkD4GM4SnNC+Yh6izwAT/oF5ae5DZ/xumXNvQ48VA+I9ya2NYHDNeqHcnUr948GUwPD+61l3I9xgbO2ljVyZdmz3Mj+mWXNXMtyI99zDN/y/fvv6MF9xH0Xy+TPNfYf+NEtn+mgIzPLPq2zYQ0K768sed4tn/+QD7V8upxPr1fbUEvIn/6ckw81+61+QnX+WvsP6s6tJW/jG/rmpWW9if/oC5aWfNNa9nRLy7oJTltb6gE4UjdRB/T7X4Tj6bX/aX9xbf0HtZXbcD4dPtGeuLLUdHrmxoY9c2uZc60Nn9PVcj4aQl3HddxF3D541kkf6S+uTT/gDPoEcHBZh7/IGfxNTuB3aip0Y2ZDTa8s9V77f7SmH/Mx8DiF397i/4+ul4bH3LK2R3PREzQBfVDeryzz6taGte5W8Ggs56zIg9aSs7Se7rF59tTxx3fw/0fXS8SjtpyHpfaBm8ALLppJbLMNjaBnp1/U86iHVzZ876Aa4YQu74W3fqZelK4fxDy9L71xbTl3t7Z8v4Y6uBW/U5/ObMhXN5a9NT6v5Bi48q9eI3xEb3cfyz9bL0rXD3BYWup5ExhUI183ltoCXxH3teBBzeqW9Rb4/qX74veD5xzHo+e+9/YPX00/8DecpfqLZsNHG8uamHXyg35jdmHM/vij57zFNmIUHm8Dj1+hD9emH25Z42j/Vtnw+Qa8srbswxvLuaiVDd+Lon9EaxSLU/iF+aVL81G/a700POD6ueUzVvhlZd8+m6Y3WVo+04WTGksOoy6gXrv3rGWb4IpZ7GNe9lfow6X1rdxDaXgsLbUDPmps+M5nY8P3McGJmmhu3/bbHM/c1iF4idzozYkB/3X6cGl9JtdWGh4bG75vNZPYWVrOU1WWHIb/4TW3nBN3y36klW3z8Dsc/ll6Ubp+4O9bWSbOa8u6FS1hrg/8OA//u2U9TF6BIb3FMT4v8fmz/9n6MRNfz8S0Bqb3QEs4Hr1B66mFXfY3lpq/8+y7e19c4veT/3r9KLn/4LmPzqMvbfgcFwzchn0eODQ2fHe9suFzw7/rL4nN3he/Sy+uqf9A2yob/mYQvVOc0G6dIwc7arB5LLdyHPnkltw26cf38UArWsu5E3xIr42fK8u59spyrv1G8GMehXwB743s20eM/u5+o3T9aC17bfzrlvO1lWXOgEttqfXMszc2/P3FzIbvhTCPq33O7+o3rkk/8PdM/ExPrRrPHDx6UlnWY2tL3ussdWdp+dsA5kUOwRcPYZN+DI15EuZwF/YtP+Hr2lLTV5b9yUKwaD3fSaNeOkVcwtn7wOQ5fDPpRxrzsDPL3gJ9uBGclnIs22rJl952nnODu+AFeo07z/fT2P8ZelG6fuDfypLX6dk9MGjFVOPXI4Obn8L39HdPns8z4K1jHHP0ST/G9VXv41vLvntpw+cZzAky185xYzw6H86ja69xiJw4yPrUf1zGY21Z71JT9dbZ8DcEHAtmYzzg5hfP95kfAqO9J17449Gn/mNs9Az0eW7ZI/R501jqBHmjOqL27KkLJ8/3NnfxefR8z3nvk35cssbyvdDaUhtaG85FuWVvd4mreoOTmBc5RSzuwuBusDhJzkz68WqtZS2lfAUO1FiN5TzwjQ3/f8jek3seJfbQcjS7C554Et6gJpv049WYX6L3gL/QFLd8TttZvqNz51kjdZ6asfX8DRMaQn31IHEJhz/6pB9q2m9Uls9cd57Pu/tr77cv7dW3j559htatB8/nsXvOi887icvW8z3Qk0/6Ma6v+nwgfu/iehsf8gk+PorPibGTD999pqbdxeeD53ONo+d7ueTUV9KPt45HN79nd57zFk8SO0dP/lF8HgMHsHgQn6MRL3K/z57a/uL52wHlOcb4CvrxUTwO4vc2fI7hS3SaGpZj9/EJL6mfT5617ZNnDwj/HT115im2b/369eOj450v6W8c4PPeV7UlLie5fjQFXPae+XPwfI+EsciJvQ9/s0/NRc++95z3vWb9+Oh4+FB5qpM4upP7QMO1zxvXTc+ev3VtPN91e4rznz3zEr5DV/4E/Xgvn2ncvnjWpMrxj7F+NzrmKOeRL8Q9+6gBwAteazz56k/Qj7cMv6DTO895p87zOTc8RS50nnUAfQS6Da7ozZPgBEedPPvD36kXpetH48kr6MiDp2Z3ns+6qbWUy4jtJ7lfxkPDwejJswZje+tfq//46HjwDBwPv4IJ9dd+5GNyhfuj/qJXZD8Yw1OqHc+e/Y3yO/nzJ+rH/Sjm0XI4S/0PvxDfaP/RM8/IG/LkIHh0nr3lVs5/jHVy9E/WD7iEOok+Yh8xit+os4hp9IXe5MVTi6h38TXLaDr89xKfk36kPfu3PYPG68Gzxrrz1G9qVTSEuosaimVwOsjYRxmH/Jz049Wo/5VDwOPRh78tU90mT9CWRx/+voN6DAzAZ+eZV+gOfL71qf+YbMLjK9mER1k24VGWTXiUZRMeZdmER1k24VGWTXiUZRMeZdmER1k24VGWTXiUZRMeZdmER1k24VGWTX/T3/T39t//ANRqG5I= 9 | 10 | 11 | 12 | 13 | eJztnG1S2zAQhuMLwFDuEQI9Rf9A+6PXoDAt1whNew9K6D1IWu7RUrhA/RLvZCMkWbLjD8XvM+MhsR3H7Ho/JWU0IoQQQgghhBBCCCGEEEIIIYTEsMy3t1nXdzE8bhz7f7Z6F0T449h/2IBtfC2278X7xfa/opfsRchynJ97nG9Hxd+TfJtkzfqqJnTdZ+67voEShqSPab796/omLEyU/Q0pT4jxVW1yXPhB+MVfXd8M2aCvz8xQceV0Q2YZeF4TvsVV8wyV9xExdUx/3zgX2bomAzonexy9PnYZ6e9he8dKj1PjmjZOBx5TIPezbCUHU976WJXcWeqLcZFTfc5W17wererzs+I4rj8brbY+5uh1qBIjISOXHC4segpB+pCwCchfZC29kYNsdW3sl+v/jv+aXiL/87dRtecLsnPFBsSYD5H6wPN+lW3ez12+Palz7ozPHOyIn7L5mRjkOR5b5K6PhcTyU/W8z4t9kPO+uq4p91n+fmFsKVOnR2XmV1on0MUndezcoxPYJ+KB6Y9CuE1c/iZ1cngzv/Lh64f57Mf0SybUxyaPgeeNS+RW9T52TR99oWrvIyV9SN4k+Tr+hvqXtmFvsBvMGhs5lcRyTUrPfcogTiDmoLaAvUqu/WScR300i64tkMv+Lfa78tt5/v4atkO9bJ0qvUSBdlIf1IK6Vt9T9hAL9VGfw2w9/wd1HnOn7jB7KKgr+j5vqI9sa+zzQb1GDP8SOfZxQ1t6oe54qvQEpU8uuWzsmAT1seY8cqwCOkAOK+MUqCGQt77J1n3AkD7ttMhtsd1RHxvExF7EhR/Fa9QRMt49ibS1ujaB752oeXK7RFkfVoNYDTsQG3hWx6CrtuadP5efMggk5sBPQS86lvtyqqr2oP2aZkhrTMr8l87L0JeSPrLkVLb4UUUfU09skX7YrPj+XaZMH+Y4rC+OT2vE7KHnXagddP/Vd570CG060OOtVe2CeVf4eB1iyEeVU+175FZFH0O3CyGmppY47orhfMbbQ69nds3puUfNTl1EU2U9npn7u/wc/Y4d9Di+Fa/NHmKsPnCtq2L8G9e0jYML1Icd7eNljEL6DK61HNKnktpCcv3LgD4VY4ef2L66rBUQecfO56RdvEbmEoTUEyZ11+hRH9uFY639ok9rJnfZ1mSs4qhkDMqmj67mfKSsD8gbvylxYqnRzN+k8sWIPUtfytRHmX7qytGWo80SqzH1WIT5jD8Y721j55Lj2uJ/2/qwfR7fmZK96DEa8/m31X045zRz13W6T+vTh8jItq8qN4ZdYE3aMlv1YRaJ2MlFtv7dLnnGpYeOmtpcG67n5Wj/dFv81ev0lsb/L3NttU+x7YvF5qf0vN7Uak3pjUjtIfLG3E34LJnrH1KTtBnDQ+Sckr+S3oZPzugDyvweV62t16yaNvHyPeq4y2eEnFOFeUJ2EYKMOdf5PYOQGLHNOLILhMjAXAsTCvURT5MyoD7i8cmgbG032Q6SZ6aUC4JZQvfaBW37F66F8tOmPmaOnHoXWNTM+evUvfLZ2HWxQ7GNpueg6TnOrn5JiH7m1Eer1x/K819Gm/p4l73eBOqDEEIIIYQQQgghhBBCCCGEENJn/gOQDkKH 14 | 15 | 16 | 17 | 18 | eJztXG1yG0UQXemHFIpb8MNY9i34AXF8DqoMnIKPYJtbEEgc+xaEQHBuAaGM7cohmCnrVZ5a3bOzsytpZPer6oos7a5W/Wamu1/PpmkcDofD4XA4HA6Hw5GL02A/bfomHiii798I+yvYi03e1APGS+P9P5sP/PhcWR8sPhg+V9YHjY8fgx0HO5n/HeeKz5H1QOMjzocz8ZnPkfXgvLmbC3I+IK4Dzsf6kYolzsf64XzUBefDBuq0W8Xk+/g75kA3zV0slsbvazWgjBcSiCm3zWJdcml836X4DXy8fJ/v/3p+fm34r+Ac5KXwx5nyOvoi5ffS74t23aS/R8vbrOvVhpw6TUP8TXLc8euhuNC+j//Vvgd8pMZarbVOKR81o21+AFdruJeuSI2hb4N9F+z7Nd3LUMiZHziuNlhjKHLxQ7DXwX4xjoHe8bZZrPO0Y/g4+Rp/y8+162GMwLSxEv18nfhtfFxtkPeM3wsu3jU6H9HPF81iThVr8BPlGI6/N81iDnbZLOdlZ8b1MEbekT1tljnZ5vVK3vPPzd3vBBcWH/E3yxz0RlxP5kWaz628OXIoc6d4b8+C/Uv2TLm/XD5qnB9yjf0t2Cthvyvn4TfDn8j1Zb7D/Q025smqVeS1MFaYixQfcX5hDXzbLK+JF8a9dbGhUZpf4TfDul6H505urRLHyq/NBy7Ai8WHVq+soj4aEn34wNy4LLxObtxlSE6eN8vzV85Jq265GoX1oacNjT71YGptyb3GeNT9XF5TtbU0F5Nxj5NXhBK9ZEh8soIxlosa+dh0fe58LGKTfMT65LORXvetA87HIkri+ZCokY8+8SPWy3/MravGxfW9rMPbIPOi68I1r0Y+csZm9J3Uk1jfgsZlaVXa35ELrs3PW85jjSz6cRZsL9g02CPhVy2P1TirkY+csanppbFWft0s8iE1lBvxWmojllYij2GNK97DZM6DxQd/jmNOxsscnVbIR2q9wHjHusJziflATSY1FGlWz5XPSfVZUefk8BE/2ydOZjSnZvPzZhXyAR9pcQT+xTHMh1aTWT1D7mtrfMmee1t9uBP8+CnZbmJ+TIkX5gF81Qb4IrV/sFSjkuCanvcVnDaL478vJF/SviK+akPK1zIeDJ2XavsT1wHOB2oD1iNtvYK/sM7k8CH7d6X93kmIt1Nhjwaq5SfztWpaKR+yjyTB/YRjYTIPQI8iWozzpZrf58H3X8QcKNiTYIfBdomPlDbbVo9gftQYz2X+r/lZ9vnOxHl8LPeMrL57F+wYfCBmy1it5VtL15zHkBrjuezbwOR80ThBbsrrP/oTWl+iBG18zOZ+PTLyrStjzkwqjR/wKfaEYq+lVpNoe9K0WBw5GYKLCKxb0R6TT9tyXgC8/R3O/Yfs3ahOPuT4xjzYpM43JCbzuSP5wppVGzSfl/btasQkEU9q1K8sfbdrn0jTHIeGFQtS2DY+rDUphw9wAI0LcQd67BDccF57Oo/frA3m5LYPhQ9+VmPV2gc0DtRxRy1xHNg2PoZar1atfeTmUxLbxof1XPgm+9pDYtv4SO2Bvi/5bow3Ms5cVdqP4hjMfVStD8H9WEu/6tNT18C6IuuJmn51EPx7aPRCtHqwVj2Re0GIzxoXF82yXqLpV9a+2hJEveTA0Etm48W+39fBnghOdox4U6tektuXk71C6F3aMwFD83E417AsPvbptcaJBNaqWudHaj+07KHL3rbkEHpi5CM+K9O3/3Ge0BNnhrVxgjWsVj6s/nmEfB4897mAV81yf70LWEfM0RNlPzZy8k2Cj73K+dhELlWif+QA4z+V56JnUhv68oH+bO6aZOkfQ3KCfmyKj9rXqxI+eI9ijN05z7ecki+w56azJpXoqSNW723p/EC+xDWI9lyypg/GXIr3J2Jcws+yn4pcCBzsES8zgxutN44c+EDE+KZZ3Hu1jXxY+wiRy/J+Ke35SskH70Nj/8PXcm7s03H8/p7gaZ98nOKD43xbz7DG9Ur+/z5dcinJR84+NPYzczMV7x8Z19gVfLxU1qw2oDdY4/zok1dxXpuT00q+wI/m+5R+y3xocyQHtfZrrbpjHcA63rY/R0LWJo8L+MD314ZNarhxjH45yu9lDA3nYxlPB64Fu6BGPkrXq6GeGSvl42qA714FH296Wml/FWv/XmEMiIg+fV7oT85ZS74b11g3+vxfECk/QV9tq700YGzL/SJd9/HsbyEfbdByzffBL8ctv5M10pRWZJ07pXO7jHPJpfq8GukpqecVauRD88GL8N7tqJ0PTePgMW7pWaxhTcmvmk6i7YNmLtW9oFSboHci+ye4Vm1IaTxtfEDD4Dqbz+FnAuSze1PxHmsmOEZbByfiXO0eHyofUmOy+NA0EZzLuqOmYcl7yNmHJev3E6NuvE98WFoV+6dNz8qxklox1u/Wc1XyN9aGUj5qh/XcCGPb+Bi6b1cbtokP6J/W5zm9wKG4bPuumurzvvhonN4Xk9OD5njOeWxXLi2/cp4mc7T7Vg/GfTEfj+06weqdokfNeSrnSFY9odUfOcfznjfOwVLn5fTyHQ6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hoyv+BxYtonY= 19 | 20 | 21 | 22 | 23 | eJzt221OgzAYAOCewOlF8OMgOj3IvP8/1xhMYXQsK1CQ50maEbJB02/eshAAAAAAAAAAAAAAAAAAgFJPtTNAx+mcvs7po+Aa6nR6n5nzL+G3vq7V2XGWHDGm7Uv99FwzU1zQP9ZFfazH+zl9184Ef3LrAMrFth7n57faGdm5dk1r3AGAbREDXI+4nmqCdS1AZH5aFzHfclO2afVR7iFMF0/s7yWW7M/vTUk8cahPPQ6c01+Wca2c03ppv2eeLzNWfm05D/WJoe/FMfEQ/v+z6FztbmycaeecsdQkn3t4H2Wu8Xnsuvfcd+t7vO0+aj8dkuPX3vkp1jNxnh+b4/cyT6fvBebK5Jg5ju0v9+7a1PvjW2/rU0rLYi/tdCvUx7oYNwD2qXZcp/b916Z0fVRantZnXaXlUfJ7/xm4VLM+9I2uGBu5J+aZxrXS+NWtsSvvteel8aZcfCmNafXLMX0evOVaAMB8lnpO9jyel66bmjDf2mip+wAAAAAAAADc4geN9i6+ 24 | 25 | 26 | 27 | 28 | eJzt20dOAzEUgOEREiBRxSEAibLhBvQtVwCyhjMAuQjloHgWkUIyGVye6/s/6SkbEhzb4/LsdB0AAAAAAAAAAAAAoHZbJrZN3KzJf/a142fGKENtTkyc5i7EiIllGz1Z/l0rbf7cyPcAQjzyHGRlO+62xHZOQlyu671SXWb6Hq3Un691E5sDryGulNdpiFsT9wOvNlpZ1yMM/UAG62p5EnVqs96WXp9+0ReielNav+yj6iTRblLz9E+lfUj73gsAfOTKl2khfbb4TnstCenDi2uH2DkP2g/SyJPnx/4bSGPsWWMsHNdarqTWnJWPGPeDfNej3x7vKz03399Z2OjC7y1AxqGJIxPHnc67caXp75Dcdfb3SGLiHDWcy54l5TzrM7eUQMPvCHjuACC9kL17a/v+lFLd38x531bDuRT3cNNJda9AQ79tCfuH1chxAW3QdC6FNELPthfP36ZCfbTWfG0M/GayTKXez/rvTPyz0HKX5GOkjjSPTav24KXfw8Cyg9wFwB8PHu8J3ROMrdc05FXGxnmf9oA913l0qD009NFS7ZnYN3GRsQwuufp+rJxFLVy+34uJ12gliUMqX5DK/DqXc6L0ppXUv9S6TPNeMwaX3MeqNmTNkcd8e8yeix0Tu1lK42+x//j2J9fxz3eunQ7Ue2/o+Tgzce73bwAAAAAAAAAAAAAAhfkFSOo3GQ== 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /canvas-faster-picking/tools/hullgen/LICENSE.txt: -------------------------------------------------------------------------------- 1 | FreeImage Public License - Version 1.0 2 | --------------------------------------------- 3 | 4 | 1. Definitions. 5 | 6 | 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 7 | 8 | 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 9 | 10 | 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 11 | 12 | 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 13 | 14 | 1.5. "Executable" means Covered Code in any form other than Source Code. 15 | 16 | 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 17 | 18 | 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 19 | 20 | 1.8. "License" means this document. 21 | 22 | 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a 23 | Modification is: 24 | 25 | A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. 26 | 27 | B. Any new file that contains any part of the Original Code or previous Modifications. 28 | 29 | 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 30 | 31 | 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control 32 | compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 33 | 34 | 1.12. "You" means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the 35 | direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. 36 | 37 | 2. Source Code License. 38 | 39 | 2.1. The Initial Developer Grant. 40 | The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: 41 | 42 | (a) to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and 43 | 44 | (b) under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell ("Utilize") the Original Code (or portions thereof), but solely to the extent that 45 | any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or 46 | combinations. 47 | 48 | 2.2. Contributor Grant. 49 | Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: 50 | 51 | (a) to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and 52 | 53 | (b) under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that 54 | may be necessary to Utilize further Modifications or combinations. 55 | 56 | 3. Distribution Obligations. 57 | 58 | 3.1. Application of License. 59 | The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or 60 | restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 61 | 62 | 3.2. Availability of Source Code. 63 | Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 64 | 65 | 3.3. Description of Modifications. 66 | You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 67 | 68 | 3.4. Intellectual Property Matters 69 | 70 | (a) Third Party Claims. 71 | If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make 72 | available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. 73 | 74 | (b) Contributor APIs. 75 | If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file. 76 | 77 | 3.5. Required Notices. 78 | You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its 79 | structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or 80 | liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of 81 | warranty, support, indemnity or liability terms You offer. 82 | 83 | 3.6. Distribution of Executable Versions. 84 | You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You 85 | describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, 86 | provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 87 | 88 | 3.7. Larger Works. 89 | You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 90 | 91 | 4. Inability to Comply Due to Statute or Regulation. 92 | 93 | If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 94 | 95 | 5. Application of this License. 96 | 97 | This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code. 98 | 99 | 6. Versions of the License. 100 | 101 | 6.1. New Versions. 102 | Floris van den Berg may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 103 | 104 | 6.2. Effect of New Versions. 105 | Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Floris van den Berg 106 | No one other than Floris van den Berg has the right to modify the terms applicable to Covered Code created under this License. 107 | 108 | 6.3. Derivative Works. 109 | If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases "FreeImage", `FreeImage Public License", "FIPL", or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the FreeImage Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 110 | 111 | 7. DISCLAIMER OF WARRANTY. 112 | 113 | COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 114 | 115 | 8. TERMINATION. 116 | 117 | This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 118 | 119 | 9. LIMITATION OF LIABILITY. 120 | 121 | UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE 122 | EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 123 | 124 | 10. U.S. GOVERNMENT END USERS. 125 | 126 | The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 127 | 128 | 11. MISCELLANEOUS. 129 | 130 | This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by Dutch law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the The Netherlands: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Almelo, The Netherlands; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the court of Almelo, The Netherlands with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 131 | 132 | 12. RESPONSIBILITY FOR CLAIMS. 133 | 134 | Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based 135 | on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute 136 | responsibility on an equitable basis. 137 | 138 | EXHIBIT A. 139 | 140 | "The contents of this file are subject to the FreeImage Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://home.wxs.nl/~flvdberg/freeimage-license.txt 141 | 142 | Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. --------------------------------------------------------------------------------