├── .gitmodules
├── .nojekyll
├── credit.html
├── favicon.png
├── images
├── eye.png
├── hide.png
├── show.png
├── filter.png
├── noise.png
├── power.png
├── callout.gif
├── error-16.png
├── showall.png
├── screenshot.png
├── diagnostic
│ ├── cc.png
│ ├── eye.png
│ ├── gc.png
│ ├── io.png
│ ├── js.png
│ ├── cache.png
│ ├── text.png
│ ├── plugin.png
│ ├── snapshot.png
│ └── sync-ipc.png
├── circlearrow.svg
├── treetwisty.svg
└── throbber.svg
├── run_webserver.sh
├── samples
└── README
├── deploy.sh
├── download_profile.sh
├── production.sh
├── run_tests.sh
├── css
├── tooltips.css
├── diagnosticBar.css
├── sourceView.css
└── tree.css
├── appcache_generator.sh
├── test.html
├── bootstrap.sh
├── js
├── tests
│ ├── 001-smoke
│ │ └── test.js
│ ├── 002-profile-load
│ │ └── test.js
│ ├── base.js
│ ├── 003-profile-filter
│ │ └── test.js
│ └── run_qunit.js
├── remoteView.js
├── QueryData.compressed.js
├── pluginView.js
├── frameView.js
├── qr
│ └── jsqrcode
│ │ ├── errorlevel.js
│ │ ├── gf256.js
│ │ ├── bitmat.js
│ │ ├── decoder.js
│ │ ├── datablock.js
│ │ ├── formatinf.js
│ │ ├── test.html
│ │ ├── datamask.js
│ │ ├── grid.js
│ │ ├── rsdecoder.js
│ │ ├── bmparser.js
│ │ ├── gf256poly.js
│ │ ├── alignpat.js
│ │ └── databr.js
├── lz4.js
├── sampleBar.js
├── log.js
├── profileCompare.js
├── diagnosticBar.js
├── tabWidget.js
├── plugins
│ └── protovis
│ │ └── index.html
├── breadcrumbTrail.js
├── FlameGraphUtils.js
├── sourceView.js
├── tabProviders.js
├── ui.js
├── fileList.js
├── videoPane.js
├── ProgressReporter.js
├── localStorage.js
├── markerTree.js
└── profileTreeManager.js
├── .travis.yml
├── sample.log
├── README.md
├── index.html
└── qunit
└── qunit-1.16.0.css
/.gitmodules:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/credit.html:
--------------------------------------------------------------------------------
1 | show.png, hide.png, eye.png by Gentleface.com
2 |
--------------------------------------------------------------------------------
/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/favicon.png
--------------------------------------------------------------------------------
/images/eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/eye.png
--------------------------------------------------------------------------------
/images/hide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/hide.png
--------------------------------------------------------------------------------
/images/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/show.png
--------------------------------------------------------------------------------
/images/filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/filter.png
--------------------------------------------------------------------------------
/images/noise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/noise.png
--------------------------------------------------------------------------------
/images/power.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/power.png
--------------------------------------------------------------------------------
/images/callout.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/callout.gif
--------------------------------------------------------------------------------
/images/error-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/error-16.png
--------------------------------------------------------------------------------
/images/showall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/showall.png
--------------------------------------------------------------------------------
/images/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/screenshot.png
--------------------------------------------------------------------------------
/images/diagnostic/cc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/cc.png
--------------------------------------------------------------------------------
/images/diagnostic/eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/eye.png
--------------------------------------------------------------------------------
/images/diagnostic/gc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/gc.png
--------------------------------------------------------------------------------
/images/diagnostic/io.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/io.png
--------------------------------------------------------------------------------
/images/diagnostic/js.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/js.png
--------------------------------------------------------------------------------
/run_webserver.sh:
--------------------------------------------------------------------------------
1 | python -m SimpleHTTPServer
2 | print "http://localhost:8000/index.html?usesample"
3 |
--------------------------------------------------------------------------------
/images/diagnostic/cache.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/cache.png
--------------------------------------------------------------------------------
/images/diagnostic/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/text.png
--------------------------------------------------------------------------------
/samples/README:
--------------------------------------------------------------------------------
1 | To run a test case manually use the query parameter '?usesample=tests/FrameView.dat'.
2 |
--------------------------------------------------------------------------------
/images/diagnostic/plugin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/plugin.png
--------------------------------------------------------------------------------
/images/diagnostic/snapshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/snapshot.png
--------------------------------------------------------------------------------
/images/diagnostic/sync-ipc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgirard/cleopatra/HEAD/images/diagnostic/sync-ipc.png
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ssh bgirard@people.mozilla.org "cd public_html/cleopatra_staging && git reset --hard HEAD && git pull && bash appcache_generator.sh && chmod -R 755 ."
3 |
--------------------------------------------------------------------------------
/download_profile.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | wget http://profile-store.commondatastorage.googleapis.com/$1 -O /tmp/downloadedProfile.json
3 | echo "Pretty printing to: $1"
4 | cat /tmp/downloadedProfile.json | python -mjson.tool > $1
5 |
--------------------------------------------------------------------------------
/production.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ssh bgirard@people.mozilla.org "cd public_html/cleopatra && git reset --hard HEAD && git pull && bash appcache_generator.sh && chmod -R 755 ."
3 | ssh cleopatra@cleopatra.io "./update-site.sh"
4 |
--------------------------------------------------------------------------------
/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | ./bootstrap.sh
6 |
7 | ./phantomjs-1.9.8/bin/phantomjs js/tests/run_qunit.js test.html
8 | SLIMERJSLAUNCHER=/Applications/Firefox.app/Contents/MacOS/firefox ./slimerjs/slimerjs js/tests/run_qunit.js $PWD/test.html
9 |
--------------------------------------------------------------------------------
/css/tooltips.css:
--------------------------------------------------------------------------------
1 | body {
2 | /* Tooltip cause scrollbars */
3 | overflow: hidden;
4 | }
5 |
6 | /* http://www.menucool.com/tooltip/css-tooltip */
7 | .csstooltip
8 | {
9 | z-index: 5;
10 | background: white;
11 | border: solid 1px black;
12 | position: absolute;
13 | padding: 5px;
14 | margin: 5px;
15 | max-width: 300px;
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/appcache_generator.sh:
--------------------------------------------------------------------------------
1 | set -e
2 | echo "CACHE MANIFEST" > cleopatra.appcache
3 | echo "# $(date)" >> cleopatra.appcache
4 | echo "" >> cleopatra.appcache
5 | echo "CACHE:" >> cleopatra.appcache
6 | find *.html js css images -not -path '*/\.*' -type f >> cleopatra.appcache
7 | echo "" >> cleopatra.appcache
8 | echo "NETWORK:" >> cleopatra.appcache
9 | echo "*" >> cleopatra.appcache
10 |
--------------------------------------------------------------------------------
/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Cleopatra QUnit
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | if [ ! -e phantomjs-1.9.8 ]; then
5 | echo "Setting up PhantomJS for testing"
6 | wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.8-macosx.zip
7 | unzip phantomjs-1.9.8-macosx > /dev/null
8 | mv phantomjs-1.9.8-macosx phantomjs-1.9.8
9 | rm phantomjs-1.9.8-macosx.zip
10 | fi
11 |
12 | if [ ! -e slimerjs ]; then
13 | echo "Setting up SlimerJS for testing"
14 | wget http://download.slimerjs.org/releases/0.9.4/slimerjs-0.9.4.zip
15 | unzip slimerjs-0.9.4.zip > /dev/null
16 | mv slimerjs-0.9.4 slimerjs
17 | fi
18 |
19 |
--------------------------------------------------------------------------------
/js/tests/001-smoke/test.js:
--------------------------------------------------------------------------------
1 | QUnit.test("Cleopatra load", function(assert) {
2 | loadCleopatra({
3 | assert: assert,
4 | testFunc: function(cleopatraObj) {
5 | // Look for the basic elements of the apge
6 | assert.ok("Cleopatra - UI for SPS" === cleopatraObj.document.title, "Check title");
7 | assert.ok(cleopatraObj.document.getElementById("datafile"), "Has upload field");
8 | assert.ok(cleopatraObj.document.getElementById("data"), "Has paste field");
9 | assert.ok(cleopatraObj.document.getElementById("parse"), "Has parse button");
10 | }
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/css/diagnosticBar.css:
--------------------------------------------------------------------------------
1 | .diagnostic {
2 | position: relative;
3 | height: 16px;
4 | background-color: white;
5 | border-bottom: 1px solid #CCC;
6 | cursor: default;
7 | background: -moz-linear-gradient(#CCC, #EEE);
8 | background: -webkit-linear-gradient(#CCC, #EEE);
9 | background: linear-gradient(#CCC, #EEE);
10 | -moz-user-select: none;
11 | -webkit-user-select: none;
12 | user-select: none;
13 | }
14 |
15 | .diagnosticItem {
16 | background: -moz-linear-gradient(#900, #E00);
17 | background: -webkit-linear-gradient(#900, #E00);
18 | background: linear-gradient(#900, #E00);
19 | border: 1px solid;
20 | border-radius: 3px;
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | env:
2 | - SLIMERJSLAUNCHER=$(which firefox) DISPLAY=:99.0 PATH=$TRAVIS_BUILD_DIR/slimerjs:$PATH
3 | addons:
4 | firefox: "33.1"
5 | before_script:
6 | - "sh -e /etc/init.d/xvfb start"
7 | - "echo 'Installing Slimer'"
8 | - "wget http://download.slimerjs.org/releases/0.9.4/slimerjs-0.9.4.zip"
9 | - "unzip slimerjs-0.9.4.zip"
10 | - "mv slimerjs-0.9.4 ./slimerjs"
11 |
12 | notifications:
13 | irc:
14 | channels:
15 | - "irc.mozilla.org#perf"
16 | template:
17 | - "BenWa: %{repository} (%{commit}) : %{message} %{build_url}"
18 | on_success: change
19 | on_failure: change
20 |
21 | script: phantomjs js/tests/run_qunit.js test.html && ./slimerjs/slimerjs js/tests/run_qunit.js $PWD/test.html
22 |
--------------------------------------------------------------------------------
/js/remoteView.js:
--------------------------------------------------------------------------------
1 | function RemoteView(url, data) {
2 | var self = this;
3 |
4 | this.url = url;
5 | this.data = data;
6 |
7 | this._container = createElement("iframe", {
8 | src: url,
9 | style: {
10 | width: "100%",
11 | height: "100%",
12 | },
13 | onload: function() {
14 | self.remoteWindow = self._container.contentWindow;
15 | self.remoteWindow.postMessage({
16 | name: "Cleopatra::LoadData",
17 | data: data,
18 | }, "*");
19 | },
20 | });
21 |
22 | }
23 |
24 | RemoteView.prototype = {
25 | url: null,
26 | data: null,
27 | _container: null,
28 | remoteWindow: null,
29 |
30 | getContainer: function() {
31 | return this._container;
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/sample.log:
--------------------------------------------------------------------------------
1 | {
2 | "threads": [
3 | {
4 | "name" : "Main Thread",
5 | "samples": [
6 | {
7 | "name": "(root)",
8 | "frames": [
9 | {
10 | "location": "Main"
11 | },
12 | {
13 | "location": "Process Event"
14 | },
15 | {
16 | "location": "js_mozilla() (in mozilla.com)"
17 | }
18 | ]
19 | },
20 | {
21 | "name": "(root)",
22 | "frames": [
23 | {
24 | "location": "Main"
25 | },
26 | {
27 | "location": "Process Event"
28 | },
29 | {
30 | "location": "onclick (in XUL)"
31 | }
32 | ]
33 | }
34 | ]
35 | }
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/js/QueryData.compressed.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | QueryData.js
4 |
5 | A function to parse data from a query string
6 |
7 | Created by Stephen Morley - http://code.stephenmorley.org/ - and released under
8 | the terms of the CC0 1.0 Universal legal code:
9 |
10 | http://creativecommons.org/publicdomain/zero/1.0/legalcode
11 |
12 | */
13 |
14 | function QueryData(_1,_2){
15 | if(_1==undefined){
16 | _1=location.search?location.search:"";
17 | }
18 | if(_1.charAt(0)=="?"){
19 | _1=_1.substring(1);
20 | }
21 | if(_1.length>0){
22 | _1=_1.replace(/\+/g," ");
23 | var _3=_1.split(/[&;]/g);
24 | for(var _4=0;_4<_3.length;_4++){
25 | var _5=_3[_4].split("=");
26 | var _6=decodeURIComponent(_5[0]);
27 | var _7=_5.length>1?decodeURIComponent(_5[1]):"";
28 | if(_2){
29 | if(!(_6 in this)){
30 | this[_6]=[];
31 | }
32 | this[_6].push(_7);
33 | }else{
34 | this[_6]=_7;
35 | }
36 | }
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/images/circlearrow.svg:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/images/treetwisty.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/css/sourceView.css:
--------------------------------------------------------------------------------
1 | .sourceViewContainer {
2 | position: absolute;
3 | top: 0;
4 | left: 0;
5 | bottom: 0;
6 | right: 0;
7 | z-index: 2000;
8 | background-color: white;
9 | }
10 |
11 | .sourceContainer {
12 | overflow: scroll;
13 | position: absolute;
14 | top: 30px;
15 | left: 0px;
16 | right: 0px;
17 | bottom: 0px;
18 | }
19 |
20 | .lineCountDiv {
21 | min-width: 30px;
22 | max-width: 30px;
23 | overflow-x: hidden;
24 | display: inline-block;
25 | float: left;
26 | }
27 |
28 | .lineSourceDiv {
29 | display: inline-block;
30 | }
31 |
32 | .sourceViewTrail {
33 | top: 0;
34 | right: 0;
35 | height: 29px;
36 | left: 0;
37 | background: -moz-linear-gradient(#FFF 50%, #F3F3F3 55%);
38 | border-bottom: 1px solid #CCC;
39 | margin: 0;
40 | padding: 0;
41 | overflow: hidden;
42 | }
43 |
44 | .sourceViewTrailItem,
45 | .sourceViewTrailButton {
46 | background: -moz-linear-gradient(#FFF 50%, #F3F3F3 55%);
47 | display: block;
48 | margin: 0;
49 | padding: 0;
50 | line-height: 29px;
51 | -moz-user-select: none;
52 | cursor: default;
53 | padding: 0 10px;
54 | font-size: 12px;
55 | border-right: 1px solid #CCC;
56 | text-overflow: ellipsis;
57 | white-space: nowrap;
58 | /*position: relative;*/
59 | }
60 |
61 | .sourceViewTrailButton {
62 | float: left;
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/js/pluginView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function(window) {
4 | function PluginView() {
5 | this._container = document.createElement("div");
6 | this._container.className = "pluginview";
7 | this._container.style.visibility = 'hidden';
8 | this._iframe = document.createElement("iframe");
9 | this._iframe.className = "pluginviewIFrame";
10 | this._container.appendChild(this._iframe);
11 | this._container.style.top = "";
12 | }
13 | PluginView.prototype = {
14 | getContainer: function PluginView_getContainer() {
15 | return this._container;
16 | },
17 | hide: function() {
18 | // get rid of the scrollbars
19 | this._container.style.top = "";
20 | this._container.style.visibility = 'hidden';
21 | },
22 | show: function() {
23 | // This creates extra scrollbar so only do it when needed
24 | this._container.style.top = "0px";
25 | this._container.style.visibility = '';
26 | },
27 | display: function(pluginName, param, data) {
28 | this._iframe.src = "js/plugins/" + pluginName + "/index.html";
29 | var self = this;
30 | this._iframe.onload = function() {
31 | self._iframe.contentWindow.initCleopatraPlugin(data, param, gSymbols);
32 | }
33 | this.show();
34 | },
35 | };
36 |
37 | window.PluginView = PluginView;
38 | }(this));
39 |
--------------------------------------------------------------------------------
/js/tests/002-profile-load/test.js:
--------------------------------------------------------------------------------
1 | QUnit.test("Cleopatra Simple Profile", function(assert) {
2 | loadCleopatra({
3 | query: "?report=1af8b3634507afe71fdd7a4902aca0d50cc20223",
4 | assert: assert,
5 | testFunc: function(cleopatraDocument) {
6 | },
7 | profileLoadFunc: function(cleopatraObj) {
8 | assert.equal(cleopatraObj.window.gNumSamples, 174, "Loaded profile");
9 | },
10 | });
11 | });
12 |
13 | QUnit.test("Cleopatra Complex Profile", function(assert) {
14 | loadCleopatra({
15 | query: "?report=4c013822c9b91ffdebfbe6b9ef300adec6d5a99f",
16 | assert: assert,
17 | testFunc: function(cleopatraObj) {
18 | },
19 | profileLoadFunc: function(cleopatraObj) {
20 | assert.equal(cleopatraObj.window.gNumSamples, 558, "Loaded profile");
21 | },
22 | });
23 | });
24 |
25 | // PhantomJS doesn't support zip.js so skip this test for it
26 | if (navigator.userAgent.indexOf("PhantomJS") == -1) {
27 | QUnit.test("Cleopatra Zip (Talos) Profile", function(assert) {
28 | loadCleopatra({
29 | query: "?zippedProfile=http://mozilla-releng-blobs.s3.amazonaws.com/blobs/Try-Non-PGO/sha512/02ce11479d9a0c03eee146c9ff18010e9eca892dd9b3ab92eed40f07fcb295a1c4a2e5ed317bbf784e0363f4f3630c4cb7117e7522e21c6d2b48fb469ed68cd5&pathInZip=profile_tresize/tresize/cycle_7.sps",
30 | assert: assert,
31 | testFunc: function(cleopatraObj) {
32 | },
33 | profileLoadFunc: function(cleopatraObj) {
34 | assert.equal(cleopatraObj.window.gNumSamples, 2646, "Loaded profile");
35 | },
36 | });
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/images/throbber.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/bgirard/cleopatra)
2 |
3 | 
4 |
5 | Cleopatra
6 | =========
7 |
8 | Cleopatra is a webpage to visualize performance profiles. It was written to be used by the Gecko Profiler but can in theory be used by any profiler that can output to JSON. The UI runs entirely client-side except for a few profile storage and retrieval option.
9 |
10 | Code
11 | ====
12 | Directory js:
13 | ui.js - Fetches profiles, dispatches heavy requests to parserWorker.js, display the processed data.
14 | parserWorker.js - Parses the profiles, handling filtering, searching and grouping.
15 | tree.js - Custom tree view control.
16 |
17 | Running
18 | =======
19 | 1) Open index.html. Note that some features, such as reading local profiles, will either require you to run a webserver using 'run_webserver.sh' if you have python installed or setting 'security.fileuri.strict_origin_policy;false' in about:config.
20 | 2) Add ?report= to an existing profile you have upload for easy testing.
21 |
22 | or
23 |
24 | 1) Install the 'Gecko Profiler Add-on'
25 | 2) Set 'profiler.url' to your local copy of index.html such as 'file:///Volumes/Guest%20OS/Users/bgirard/ben/sps/cleopatra/index.html' and 'Analyze' a profile.
26 |
27 | or
28 |
29 | 1) Open index.html and load a profile from a file
30 |
31 | Contributing
32 | ============
33 | 1) Fork 'https://github.com/bgirard/cleopatra' on github.
34 | 2) Push changes to your local fork.
35 | 3) Submit a github pull request
36 |
--------------------------------------------------------------------------------
/js/frameView.js:
--------------------------------------------------------------------------------
1 | function FrameView() {
2 | this._container = document.createElement("div");
3 | this._container.className = "frameViewContainer";
4 |
5 | this._busyCover = document.createElement("div");
6 | this._busyCover.className = "busyCover";
7 | this._container.appendChild(this._busyCover);
8 |
9 | this._svg = this._createSvg();
10 | this.display();
11 | document.body.innerHTML ="";
12 | document.body.appendChild(this._svg);
13 | document.blah = sdf;
14 | }
15 |
16 | FrameView.prototype = {
17 | getContainer: function SourceView_getContainer() {
18 | return this._container;
19 | },
20 | _createSvg: function SourceView__createSvg() {
21 | var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
22 | svg.setAttribute("version", "2.0");
23 | return svg;
24 | },
25 | dataIsOutdated: function HistogramView_dataIsOutdated() {
26 | this._busyCover.classList.add("busy");
27 | },
28 | display: function SourceView_display(histogramData, frameStart, widthSum, highlightedCallstack) {
29 | frameStart = [1, 16, 32, 100, 110, 115];
30 | var path = "m ";
31 | for (var i = 0; i < frameStart.length - 1; i++) {
32 | var start = frameStart[i];
33 | var end = frameStart[i+1];
34 | var time = end - start;
35 | path += (i * 10) + "," + (50 - time) + " ";
36 | }
37 | var pathElem = document.createElementNS("http://www.w3.org/2000/svg", "path");
38 | pathElem.setAttribute("d", path);
39 | pathElem.setAttribute("stroke", "black");
40 | pathElem.setAttribute("stroke-width", "5");
41 | this._svg.appendChild(pathElem);
42 |
43 | },
44 | };
45 |
46 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/errorlevel.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | function ErrorCorrectionLevel(ordinal, bits, name)
27 | {
28 | this.ordinal_Renamed_Field = ordinal;
29 | this.bits = bits;
30 | this.name = name;
31 | this.__defineGetter__("Bits", function()
32 | {
33 | return this.bits;
34 | });
35 | this.__defineGetter__("Name", function()
36 | {
37 | return this.name;
38 | });
39 | this.ordinal=function()
40 | {
41 | return this.ordinal_Renamed_Field;
42 | }
43 | }
44 |
45 | ErrorCorrectionLevel.forBits=function( bits)
46 | {
47 | if (bits < 0 || bits >= FOR_BITS.length)
48 | {
49 | throw "ArgumentException";
50 | }
51 | return FOR_BITS[bits];
52 | }
53 |
54 | var L = new ErrorCorrectionLevel(0, 0x01, "L");
55 | var M = new ErrorCorrectionLevel(1, 0x00, "M");
56 | var Q = new ErrorCorrectionLevel(2, 0x03, "Q");
57 | var H = new ErrorCorrectionLevel(3, 0x02, "H");
58 | var FOR_BITS = new Array( M, L, H, Q);
59 |
--------------------------------------------------------------------------------
/js/lz4.js:
--------------------------------------------------------------------------------
1 | /* Based on node-lz4, but reformatted and made stand-alone.
2 | Semicolons added. The node-lz4 js code uses some of the
3 | most atrocious JS formatting I have ever seen. */
4 |
5 |
6 | /**
7 | * Decode an encoded chunk. Assumptions: input contains all sequences of a
8 | * chunk, output is large enough to receive the decoded data.
9 | * If the output buffer is too small, an error will be thrown.
10 | * If the returned value is negative, an error occured at the returned offset.
11 | *
12 | * @param input {Uint8Array} input data
13 | * @param output {Uint8Array} output data
14 | * @return {Number} number of decoded bytes
15 | * @private
16 | */
17 | function LZ4_uncompressChunk (input, output) {
18 | // Process each sequence in the incoming data
19 | for (var i = 0, n = input.length, j = 0; i < n;) {
20 | var token = input[i++];
21 |
22 | // Literals
23 | // length of literals
24 | var literals_length = (token >> 4);
25 | for (var l = literals_length + 240;
26 | l === 255;
27 | literals_length += (l = input[i++]))
28 | { }
29 |
30 | // Copy the literals
31 | if (literals_length > 0) {
32 | var end = i + literals_length;
33 | while (i < end) output[j++] = input[i++];
34 | }
35 |
36 | // End of buffer?
37 | if (i === n) return j;
38 |
39 | // Match copy
40 | // 2 bytes offset (little endian)
41 | var offset = input[i++] | (input[i++] << 8);
42 |
43 | // 0 is an invalid offset value
44 | if (offset === 0) return -(i-2);
45 |
46 | // length of match copy
47 | var match_length = (token & 0xf);
48 | for (var l = match_length + 240;
49 | l === 255;
50 | match_length += (l = input[i++]))
51 | { }
52 | match_length += 4; // minmatch = 4
53 |
54 | // Copy the match
55 | var pos = j - offset; // position of the match copy in the current output
56 | var end = j + match_length;
57 | while (j < end) output[j++] = output[pos++];
58 | }
59 |
60 | return j;
61 | }
62 |
--------------------------------------------------------------------------------
/js/tests/base.js:
--------------------------------------------------------------------------------
1 | QUnit.config.reorder = false;
2 |
3 | function loadCleopatra(obj) {
4 | var qunitWaitForLoad = obj.assert.async();
5 |
6 | const TEST_CLEOPATRA_IFRAME_ID = "test_cleopatra";
7 | if (document.getElementById(TEST_CLEOPATRA_IFRAME_ID)) {
8 | var frameToRemove = document.getElementById(TEST_CLEOPATRA_IFRAME_ID);
9 | frameToRemove.parentNode.removeChild(frameToRemove);
10 | }
11 |
12 | var iframe = document.createElement("iframe");
13 | iframe.id = TEST_CLEOPATRA_IFRAME_ID;
14 | iframe.style.position = "absolute"
15 | iframe.style.width = "100%";
16 | iframe.style.height = "1024px";
17 |
18 | iframe.onload = function() {
19 | var cleopatraObj = {
20 | iframe: iframe,
21 | document: iframe.contentDocument,
22 | window: iframe.contentDocument.defaultView,
23 | treeDisplayCallback: function(callback) {
24 | var qunitWait = obj.assert.async();
25 | iframe.contentDocument.addEventListener('cleopatra_updated_tree', function (e) {
26 | callback(cleopatraObj);
27 | qunitWait();
28 | });
29 | },
30 | }
31 |
32 | if (obj.testFunc) {
33 | obj.testFunc(cleopatraObj);
34 | }
35 |
36 | if (obj.profileLoadFunc) {
37 | var qunitWaitForProfileLoad = obj.assert.async();
38 | iframe.contentDocument.addEventListener('cleopatra_profile_load', function (e) {
39 | obj.profileLoadFunc(cleopatraObj);
40 | qunitWaitForProfileLoad();
41 | });
42 | }
43 |
44 | if (obj.updatedFiltersFunc) {
45 | var qunitWait = obj.assert.async();
46 | iframe.contentDocument.addEventListener('cleopatra_updated_filter', function (e) {
47 | obj.updatedFiltersFunc(cleopatraObj);
48 | qunitWait();
49 | });
50 | }
51 |
52 | qunitWaitForLoad();
53 | };
54 | iframe.src = "index.html" + (obj.query || "")
55 | document.body.appendChild(iframe);
56 | }
57 |
58 | function shownSamples(cleopatraObj) {
59 | var shownSamples = cleopatraObj.window.gCurrentlyShownSampleData;
60 | var c = 0;
61 | for (var i = 0; i < shownSamples.length; i++) {
62 | if (shownSamples[i] != null) {
63 | c++;
64 | }
65 | }
66 | return c;
67 | }
68 |
--------------------------------------------------------------------------------
/js/tests/003-profile-filter/test.js:
--------------------------------------------------------------------------------
1 | QUnit.test("Search Filter", function(assert) {
2 | loadCleopatra({
3 | query: "?report=4c013822c9b91ffdebfbe6b9ef300adec6d5a99f&search=mach_msg_trap",
4 | assert: assert,
5 | testFunc: function(cleopatraObj) {
6 | },
7 | profileLoadFunc: function(cleopatraObj) {
8 | },
9 | updatedFiltersFunc: function(cleopatraObj) {
10 | var samples = shownSamples(cleopatraObj);
11 |
12 | // Sample count for one of the two threads in the profile
13 | assert.ok(samples === 339 || samples === 28, "Loaded profile");
14 | }
15 | });
16 | });
17 |
18 | QUnit.test("Select Filter", function(assert) {
19 | loadCleopatra({
20 | query: "?report=4c013822c9b91ffdebfbe6b9ef300adec6d5a99f&select=200,400",
21 | assert: assert,
22 | testFunc: function(cleopatraObj) {
23 | },
24 | profileLoadFunc: function(cleopatraObj) {
25 | },
26 | updatedFiltersFunc: function(cleopatraObj) {
27 | var samples = shownSamples(cleopatraObj);
28 |
29 | // Sample count for one of the two threads in the profile are both 150
30 | assert.ok(samples === 150, "Loaded profile");
31 | }
32 | });
33 | });
34 |
35 | QUnit.test("Restore Selection", function(assert) {
36 | loadCleopatra({
37 | query: "?report=1af8b3634507afe71fdd7a4902aca0d50cc20223&selection=0,1,24",
38 | assert: assert,
39 | testFunc: function(cleopatraObj) {
40 | cleopatraObj.treeDisplayCallback(function(cleopatraObj) {
41 | assert.equal(cleopatraObj.window.gTreeManager.serializeCurrentSelectionSnapshot(), "0,1,24", "Restored the selection correctly");
42 | });
43 | },
44 | profileLoadFunc: function(cleopatraObj) {
45 | assert.ok(cleopatraObj.window.gNumSamples === 174, "Loaded profile");
46 | },
47 | });
48 | });
49 |
50 | QUnit.test("Invert & Restore Selection", function(assert) {
51 | loadCleopatra({
52 | query: "?report=1af8b3634507afe71fdd7a4902aca0d50cc20223&invertCallback=true&selection=\"(total)\",24,1",
53 | assert: assert,
54 | testFunc: function(cleopatraObj) {
55 | cleopatraObj.treeDisplayCallback(function(cleopatraObj) {
56 | assert.equal(cleopatraObj.window.gTreeManager.serializeCurrentSelectionSnapshot(), "\"(total)\",24,1", "Restored the selection correctly");
57 | });
58 | },
59 | profileLoadFunc: function(cleopatraObj) {
60 | assert.ok(cleopatraObj.window.gNumSamples === 174, "Loaded profile");
61 | },
62 | });
63 | });
64 |
65 |
--------------------------------------------------------------------------------
/js/sampleBar.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function(window) {
4 | function SampleBar() {
5 | this._container = document.createElement("div");
6 | this._container.id = "sampleBar";
7 | this._container.className = "sideBar";
8 |
9 | this._header = document.createElement("h2");
10 | this._header.innerHTML = "Selection - Most time spent in:";
11 | this._header.alt = "This shows the heaviest leaf of the selected sample. Use this to get a quick glimpse of where the selection is spending most of its time.";
12 | this._container.appendChild(this._header);
13 |
14 | this._text = document.createElement("ul");
15 | this._text.style.whiteSpace = "pre";
16 | this._text.innerHTML = "Sample text";
17 | this._container.appendChild(this._text);
18 | }
19 |
20 | SampleBar.prototype = {
21 | getContainer: function SampleBar_getContainer() {
22 | return this._container;
23 | },
24 | setSample: function SampleBar_setSample(sample) {
25 | var str = "";
26 | var list = [];
27 |
28 | this._text.innerHTML = "";
29 |
30 | for (var i = 0; i < sample.length; i++) {
31 | var functionObj = gMergeFunctions ? gFunctions[sample[i]] : gFunctions[symbols[sample[i]].functionIndex];
32 | if (!functionObj)
33 | continue;
34 | var functionItem = document.createElement("li");
35 | var functionLink = document.createElement("a");
36 | functionLink.textContent = functionLink.title = functionObj.functionName;
37 | functionLink.href = "#";
38 | functionItem.appendChild(functionLink);
39 | this._text.appendChild(functionItem);
40 | list.push(functionObj.functionName);
41 | functionLink.selectIndex = i;
42 | functionLink.onclick = function() {
43 | var selectedFrames = [];
44 | if (gInvertCallstack) {
45 | for (var i = 0; i <= this.selectIndex; i++) {
46 | var functionObj = gMergeFunctions ? gFunctions[sample[i]] : gFunctions[symbols[sample[i]].functionIndex];
47 | selectedFrames.push(functionObj.functionName);
48 | }
49 | } else {
50 | for (var i = sample.length - 1; i >= this.selectIndex; i--) {
51 | var functionObj = gMergeFunctions ? gFunctions[sample[i]] : gFunctions[symbols[sample[i]].functionIndex];
52 | selectedFrames.push(functionObj.functionName);
53 | }
54 | }
55 | gTreeManager.setSelection(selectedFrames);
56 | return false;
57 | }
58 | }
59 | return list;
60 | }
61 | }
62 |
63 | window.SampleBar = SampleBar;
64 | }(this));
65 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Cleopatra - UI for SPS
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/js/log.js:
--------------------------------------------------------------------------------
1 | var GeckoLogHandler = function() {
2 | this.container = createElement("div", {
3 | className: "logContainer",
4 | style: {
5 | height: "100%",
6 | overflow: "scroll",
7 | },
8 | });
9 |
10 | this.logWidget = createElement("div", {
11 | className: "logWidget",
12 | style: {
13 | background: "linear-gradient(#FFF, #FFF 50%, #F0F5FF 50%, #F0F5FF) repeat scroll 0% 0% / 100px 32px transparent",
14 | lineHeight: "16px",
15 | paddingLeft: "2px",
16 | minHeight: "100%",
17 | overflow: "auto",
18 | }
19 | });
20 | this.container.appendChild(this.logWidget);
21 |
22 | //this.busyCover = createElement("div", { className: "busyCover" });
23 | //this.busyCover.classList.add("busy");
24 | //this.container.appendChild(this.busyCover);
25 | }
26 |
27 | GeckoLogHandler.prototype = {
28 | getContainer: function GeckoLogHandler_getContainer() {
29 | return this.container;
30 | },
31 | setLogData: function GeckoLogHandler_setLogData(data) {
32 | this.logWidget.innerHTML = ""; // clear
33 | for (var i = 0; i < data.entries.length; i++) {
34 | var logEntry = data.entries[i];
35 | var logLine = createElement("div", {
36 | className: "logLine",
37 | textContent: logEntry.name,
38 | logEntry: logEntry,
39 | onmouseover: function() {
40 | if (this.mouseOverMarker) {
41 | return;
42 | }
43 | this.mouseOverMarker = window.gHistogramContainer.addMarker("Log", this.logEntry.thread, this.logEntry.time);
44 | if (this.logEntry.name.lastIndexOf("data:image/png;base64,", 0) === 0) {
45 | this.preview = createElement("img", {
46 | src: this.logEntry.name,
47 | style: {
48 | border: "solid 1px black",
49 | backgroundColor: "#FFF",
50 | backgroundImage: "linear-gradient(45deg, #F0F 25%, transparent 25%,transparent 75%, #F0F 75%, #F0F 100%), linear-gradient(45deg, #F0F 25%, transparent 25%,transparent 75%, #F0F 75%, #F0F 100%)",
51 | backgroundSize: "32px 32px",
52 | backgroundPosition: "0 0, 16px 16px",
53 | position: "absolute",
54 | top: "0px",
55 | left: "0px",
56 | },
57 | });
58 | document.body.appendChild(this.preview);
59 | }
60 | },
61 | onmouseout: function() {
62 | if (this.mouseOverMarker) {
63 | window.gHistogramContainer.removeMarker(this.mouseOverMarker);
64 | this.mouseOverMarker = null;
65 | }
66 | if (this.preview) {
67 | document.body.removeChild(this.preview);
68 | this.preview = null;
69 | }
70 | },
71 | });
72 | this.logWidget.appendChild(logLine);
73 | }
74 | },
75 | };
76 |
77 |
--------------------------------------------------------------------------------
/js/profileCompare.js:
--------------------------------------------------------------------------------
1 | function ProfileComparator(topLevelDiv) {
2 | var self = this;
3 |
4 | this._container = document.createElement("div");
5 | this._container.className = "profileComparatorDiv";
6 |
7 | this._side1 = document.createElement("div");
8 | this._side1.id = "side1";
9 | this._side1.className = "profileComparatorSide1";
10 | this._side2 = document.createElement("div");
11 | this._side2.id = "side2";
12 | this._side2.className = "profileComparatorSide2";
13 | this._side = [this._side1, this._side2];
14 | this._container.appendChild(this._side1);
15 | this._container.appendChild(this._side2);
16 |
17 | // Take every element in the topLevelDiv and nest it in
18 | // a profile comparator div
19 | while (topLevelDiv.firstChild) {
20 | var elemToMove = topLevelDiv.firstChild;
21 | topLevelDiv.removeChild(elemToMove);
22 | this._side1.appendChild(elemToMove);
23 | }
24 | topLevelDiv.appendChild(this._container);
25 |
26 | // create an iframe for side2
27 | this._side2iFrame = document.createElement("iframe");
28 | this._side2iFrame.src = "index.html?";
29 | this._side2iFrame.onload = function() {
30 | //self._side2iFrame.contentWindow.enterProgressUI();
31 | }
32 | this._side2.appendChild(this._side2iFrame);
33 | this._side1.window = window;
34 | this._side2.window = self._side2iFrame.contentWindow;
35 |
36 | this._side1.window.comparator_changeFocus = function(elem) {
37 | self._changeFocus(self._side1, self._side2, elem);
38 | }
39 | this._side2.window.comparator_changeFocus = function(elem) {
40 | self._changeFocus(self._side2, self._side1, elem);
41 | }
42 | this._side1.window.comparator_setSelection = function(frames, frameData) {
43 | self._setSelection(self._side1, self._side2, frames, frameData);
44 | }
45 | this._side2.window.comparator_setSelection = function(frames, frameData) {
46 | self._setSelection(self._side2, self._side1, frames, frameData);
47 | }
48 |
49 | return this;
50 | }
51 |
52 | ProfileComparator.prototype = {
53 | getContainer: function ProfileComparator_getContainer() {
54 | return this._container;
55 | },
56 | _isActive: function ProfileComparator__isActive(div) {
57 | var focus = document.activeElement;
58 | while (focus != null) {
59 | if (focus == div) {
60 | return true;
61 | }
62 | focus = focus.parentNode;
63 | }
64 | return false;
65 | },
66 | _changeFocus: function ProfileComparator__changeFocus(divSrc, divDest, elem) {
67 | if (!this._isActive(divSrc))
68 | return;
69 |
70 | elem.focus();
71 | },
72 | _setSelection: function ProfileComparator__setSelection(divSrc, divDest, frames, frameData) {
73 | if (!this._isActive(divSrc))
74 | return;
75 |
76 | //dump("DIV: " + divDest.id + " has focus " + divDest.hasFocus() + "\n\n\n\n\n");
77 | divDest.window.comparator_receiveSelection(frames, frameData);
78 | },
79 | };
80 |
--------------------------------------------------------------------------------
/js/diagnosticBar.js:
--------------------------------------------------------------------------------
1 | function DiagnosticBar() {
2 | this._container = document.createElement("div");
3 | this._container.className = "diagnostic";
4 | }
5 |
6 | DiagnosticBar.prototype = {
7 | getContainer: function DiagnosticBar_getContainer() {
8 | return this._container;
9 | },
10 | setDetailsListener: function(callback) {
11 | this._detailsListener = callback;
12 | },
13 | _addDiagnosticItem: function(x, width, imageFile, title, details, onclickDetails) {
14 | var self = this;
15 | x = x * 100;
16 | width = width * 100;
17 | if (width < 0.1)
18 | width = 0.1;
19 |
20 | var diagnosticGradient = document.createElement("a");
21 | diagnosticGradient.className = "diagnosticItem";
22 |
23 | var diagnostic = document.createElement("a");
24 |
25 | var backgroundImageStr = "url('images/diagnostic/"+imageFile+"')";
26 | diagnostic.style.position = "absolute";
27 | diagnostic.style.backgroundImage = backgroundImageStr;
28 | diagnostic.style.backgroundRepeat = "no-repeat";
29 | diagnostic.style.backgroundPosition = "center";
30 | diagnostic.style.width = "100%";
31 | diagnostic.style.height = "100%";
32 | diagnostic.title = title + (details?"\n"+details:"");
33 |
34 | diagnosticGradient.style.position = "absolute";
35 | diagnosticGradient.style.width = width + "%";
36 | diagnosticGradient.style.height = "100%";
37 | diagnosticGradient.style.backgroundRepeat = "no-repeat";
38 | diagnosticGradient.style.backgroundPosition = "center";
39 | diagnosticGradient.style.left = x + "%";
40 |
41 | if (onclickDetails) {
42 | diagnostic.onclick = function() {
43 | if (self._detailsListener) {
44 | self._detailsListener(onclickDetails);
45 | }
46 | };
47 | }
48 | diagnosticGradient.appendChild(diagnostic);
49 | this._container.appendChild(diagnosticGradient);
50 |
51 | return true;
52 | },
53 | hide: function HistogramContainer_hide() {
54 | this._container.style.display = "none";
55 | },
56 | display: function DiagnosticBar_display(diagnosticItems, boundaries) {
57 | var self = this;
58 | this._container.style.display = "none";
59 | this._container.innerHTML = "";
60 |
61 | var addedAnyDiagnosticItem = diagnosticItems.map(function addOneItem(item) {
62 | var x1 = (item.start - boundaries.min) / (boundaries.max - boundaries.min);
63 | var x2 = (item.end - boundaries.min) / (boundaries.max - boundaries.min);
64 | var width = (item.start - boundaries.min) / (boundaries.max - boundaries.min);
65 | return self._addDiagnosticItem(x1, x2-x1, item.imageFile, item.title, item.details, item.onclickDetails);
66 | }).some(function (didAdd) { return didAdd; });
67 |
68 | if (!addedAnyDiagnosticItem) {
69 | this._container.style.display = "none";
70 | } else {
71 | this._container.style.display = "";
72 | }
73 | //this._container.innerHTML = w; //JSON.stringify(histogramData);
74 | },
75 | };
76 |
77 |
78 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/gf256.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | function GF256( primitive)
27 | {
28 | this.expTable = new Array(256);
29 | this.logTable = new Array(256);
30 | var x = 1;
31 | for (var i = 0; i < 256; i++)
32 | {
33 | this.expTable[i] = x;
34 | x <<= 1; // x = x * 2; we're assuming the generator alpha is 2
35 | if (x >= 0x100)
36 | {
37 | x ^= primitive;
38 | }
39 | }
40 | for (var i = 0; i < 255; i++)
41 | {
42 | this.logTable[this.expTable[i]] = i;
43 | }
44 | // logTable[0] == 0 but this should never be used
45 | var at0=new Array(1);at0[0]=0;
46 | this.zero = new GF256Poly(this, new Array(at0));
47 | var at1=new Array(1);at1[0]=1;
48 | this.one = new GF256Poly(this, new Array(at1));
49 |
50 | this.__defineGetter__("Zero", function()
51 | {
52 | return this.zero;
53 | });
54 | this.__defineGetter__("One", function()
55 | {
56 | return this.one;
57 | });
58 | this.buildMonomial=function( degree, coefficient)
59 | {
60 | if (degree < 0)
61 | {
62 | throw "System.ArgumentException";
63 | }
64 | if (coefficient == 0)
65 | {
66 | return zero;
67 | }
68 | var coefficients = new Array(degree + 1);
69 | for(var i=0;i> 5;
37 | if ((width & 0x1f) != 0)
38 | {
39 | rowSize++;
40 | }
41 | this.rowSize = rowSize;
42 | this.bits = new Array(rowSize * height);
43 | for(var i=0;i> 5);
66 | return ((URShift(this.bits[offset], (x & 0x1f))) & 1) != 0;
67 | }
68 | this.set_Renamed=function( x, y)
69 | {
70 | var offset = y * this.rowSize + (x >> 5);
71 | this.bits[offset] |= 1 << (x & 0x1f);
72 | }
73 | this.flip=function( x, y)
74 | {
75 | var offset = y * this.rowSize + (x >> 5);
76 | this.bits[offset] ^= 1 << (x & 0x1f);
77 | }
78 | this.clear=function()
79 | {
80 | var max = this.bits.length;
81 | for (var i = 0; i < max; i++)
82 | {
83 | this.bits[i] = 0;
84 | }
85 | }
86 | this.setRegion=function( left, top, width, height)
87 | {
88 | if (top < 0 || left < 0)
89 | {
90 | throw "Left and top must be nonnegative";
91 | }
92 | if (height < 1 || width < 1)
93 | {
94 | throw "Height and width must be at least 1";
95 | }
96 | var right = left + width;
97 | var bottom = top + height;
98 | if (bottom > this.height || right > this.width)
99 | {
100 | throw "The region must fit inside the matrix";
101 | }
102 | for (var y = top; y < bottom; y++)
103 | {
104 | var offset = y * this.rowSize;
105 | for (var x = left; x < right; x++)
106 | {
107 | this.bits[offset + (x >> 5)] |= 1 << (x & 0x1f);
108 | }
109 | }
110 | }
111 | }
--------------------------------------------------------------------------------
/js/qr/jsqrcode/decoder.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | Decoder={};
27 | Decoder.rsDecoder = new ReedSolomonDecoder(GF256.QR_CODE_FIELD);
28 |
29 | Decoder.correctErrors=function( codewordBytes, numDataCodewords)
30 | {
31 | var numCodewords = codewordBytes.length;
32 | // First read into an array of ints
33 | var codewordsInts = new Array(numCodewords);
34 | for (var i = 0; i < numCodewords; i++)
35 | {
36 | codewordsInts[i] = codewordBytes[i] & 0xFF;
37 | }
38 | var numECCodewords = codewordBytes.length - numDataCodewords;
39 | try
40 | {
41 | Decoder.rsDecoder.decode(codewordsInts, numECCodewords);
42 | //var corrector = new ReedSolomon(codewordsInts, numECCodewords);
43 | //corrector.correct();
44 | }
45 | catch ( rse)
46 | {
47 | throw rse;
48 | }
49 | // Copy back into array of bytes -- only need to worry about the bytes that were data
50 | // We don't care about errors in the error-correction codewords
51 | for (var i = 0; i < numDataCodewords; i++)
52 | {
53 | codewordBytes[i] = codewordsInts[i];
54 | }
55 | }
56 |
57 | Decoder.decode=function(bits)
58 | {
59 | var parser = new BitMatrixParser(bits);
60 | var version = parser.readVersion();
61 | var ecLevel = parser.readFormatInformation().ErrorCorrectionLevel;
62 |
63 | // Read codewords
64 | var codewords = parser.readCodewords();
65 |
66 | // Separate into data blocks
67 | var dataBlocks = DataBlock.getDataBlocks(codewords, version, ecLevel);
68 |
69 | // Count total number of data bytes
70 | var totalBytes = 0;
71 | for (var i = 0; i < dataBlocks.length; i++)
72 | {
73 | totalBytes += dataBlocks[i].NumDataCodewords;
74 | }
75 | var resultBytes = new Array(totalBytes);
76 | var resultOffset = 0;
77 |
78 | // Error-correct and copy data blocks together into a stream of bytes
79 | for (var j = 0; j < dataBlocks.length; j++)
80 | {
81 | var dataBlock = dataBlocks[j];
82 | var codewordBytes = dataBlock.Codewords;
83 | var numDataCodewords = dataBlock.NumDataCodewords;
84 | Decoder.correctErrors(codewordBytes, numDataCodewords);
85 | for (var i = 0; i < numDataCodewords; i++)
86 | {
87 | resultBytes[resultOffset++] = codewordBytes[i];
88 | }
89 | }
90 |
91 | // Decode the contents of that stream of bytes
92 | var reader = new QRCodeDataBlockReader(resultBytes, version.VersionNumber, ecLevel.Bits);
93 | return reader;
94 | //return DecodedBitStreamParser.decode(resultBytes, version, ecLevel);
95 | }
96 |
--------------------------------------------------------------------------------
/js/tests/run_qunit.js:
--------------------------------------------------------------------------------
1 | var system = require('system');
2 |
3 | /**
4 | * Wait until the test condition is true or a timeout occurs. Useful for waiting
5 | * on a server response or for a ui change (fadeIn, etc.) to occur.
6 | *
7 | * @param testFx javascript condition that evaluates to a boolean,
8 | * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
9 | * as a callback function.
10 | * @param onReady what to do when testFx condition is fulfilled,
11 | * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
12 | * as a callback function.
13 | * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
14 | */
15 | function waitFor(testFx, onReady, timeOutMillis) {
16 | var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 30001, //< Default Max Timout is 3s
17 | start = new Date().getTime(),
18 | condition = false,
19 | interval = setInterval(function() {
20 | if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
21 | // If not time-out yet and condition not yet fulfilled
22 | condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
23 | } else {
24 | if(!condition) {
25 | // If condition still not fulfilled (timeout but condition is 'false')
26 | console.log("'waitFor()' timeout");
27 | phantom.exit(1);
28 | } else {
29 | // Condition fulfilled (timeout and/or condition is 'true')
30 | console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
31 | typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
32 | clearInterval(interval); //< Stop this interval
33 | }
34 | }
35 | }, 100); //< repeat check every 250ms
36 | };
37 |
38 |
39 | if (system.args.length !== 2) {
40 | console.log('Usage: run-qunit.js URL');
41 | phantom.exit(1);
42 | }
43 |
44 | var page = require('webpage').create();
45 |
46 | // Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
47 | page.onConsoleMessage = function(msg) {
48 | console.log(msg);
49 | };
50 |
51 | page.open(system.args[1], function(status){
52 | if (status !== "success") {
53 | console.log("Unable to access network: " + system.args[1]);
54 | phantom.exit(1);
55 | } else {
56 | waitFor(function(){
57 | return page.evaluate(function(){
58 | var el = document.getElementById('qunit-testresult');
59 | if (el && el.textContent.match('completed')) {
60 | return true;
61 | }
62 | return false;
63 | });
64 | }, function(){
65 | var failedNum = page.evaluate(function(){
66 | var el = document.getElementById('qunit-testresult');
67 | console.log(el.textContent);
68 | try {
69 | return el.getElementsByClassName('failed')[0].innerHTML;
70 | } catch (e) { }
71 | return 10000;
72 | });
73 | phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0);
74 | });
75 | }
76 | });
77 |
78 |
--------------------------------------------------------------------------------
/js/tabWidget.js:
--------------------------------------------------------------------------------
1 | var HistogramContainer;
2 |
3 | (function () {
4 | function createCanvas() {
5 | var canvas = document.createElement("canvas");
6 | canvas.style.width = "100%";
7 | canvas.style.height = "60px";
8 | return canvas;
9 | }
10 |
11 | function createElement(name, props) {
12 | var el = document.createElement(name);
13 |
14 | for (var key in props) {
15 | if (key === "style") {
16 | for (var styleName in props.style) {
17 | el.style[styleName] = props.style[styleName];
18 | }
19 | } else {
20 | el[key] = props[key];
21 | }
22 | }
23 |
24 | return el;
25 | }
26 |
27 | TabWidget = function () {
28 | this.tabs = {};
29 | this.widget = createElement("div", {
30 | className: "tabWidget",
31 | style: {
32 | height: "100%",
33 | display: "flex",
34 | flexDirection: "column",
35 | },
36 | });
37 | this.tabList = createElement("div", {
38 | className: "tabList tabrow",
39 | style: {
40 | background: "whitesmoke",
41 | },
42 | });
43 | this.tabContainer = createElement("div", {
44 | className: "tabContainer",
45 | style: {
46 | flex: "1 1 0%",
47 | overflow: "hidden",
48 | },
49 | });
50 | this.widget.appendChild(this.tabList);
51 | this.widget.appendChild(this.tabContainer);
52 | }
53 |
54 | TabWidget.prototype = {
55 | tabs: null,
56 | container: null,
57 | currentTab: null,
58 | tabList: null,
59 |
60 | addTab: function (tabName, tabContainer) {
61 | this.tabs[tabName] = tabContainer;
62 | if (this.currentTab == null) {
63 | this.selectTab(tabName);
64 | } else if (this.currentTab == tabName) {
65 | this.currentTab = null; // FORCE
66 | this.selectTab(tabName);
67 | }
68 | this._updateTabList();
69 | },
70 |
71 | getContainer: function() {
72 | return this.widget;
73 | },
74 |
75 | getTab: function (tabName) {
76 | return this.tabs[tabName];
77 | },
78 |
79 | selectTab: function (tabName) {
80 | if (this.tabs[tabName] == null) {
81 | throw "Tab does not exist";
82 | }
83 | if (this.currentTab == tabName) {
84 | return;
85 | }
86 | // Handle lazy tab
87 | if (typeof(this.tabs[tabName]) == "function") {
88 | this.tabs[tabName] = this.tabs[tabName]();
89 | }
90 | this.tabContainer.innerHTML = "";
91 | this.tabContainer.appendChild(this.tabs[tabName]);
92 | this.currentTab = tabName;
93 | this._updateTabList();
94 | },
95 |
96 | _updateTabList: function () {
97 | var self = this;
98 | this.tabList.innerHTML = "";
99 | // See http://css-tricks.com/better-tabs-with-round-out-borders/
100 | for (var i in this.tabs) {
101 | var tabTitle = i;
102 | var tabTitleLi = createElement("li", {
103 | });
104 | var tabTitleDiv = createElement("a", {
105 | textContent: i,
106 | href: "#",
107 | tabName: i,
108 | onclick: function() {
109 | self.selectTab(this.tabName);
110 | return false;
111 | },
112 | });
113 | if (i == this.currentTab) {
114 | tabTitleLi.className = "selected";
115 | }
116 | tabTitleLi.appendChild(tabTitleDiv);
117 | this.tabList.appendChild(tabTitleLi);
118 | }
119 | if (Object.keys(this.tabs).length < 2) {
120 | this.tabList.style.display = "none";
121 | } else {
122 | this.tabList.style.display = "initial";
123 | }
124 | },
125 | }
126 | }());
127 |
128 |
--------------------------------------------------------------------------------
/js/plugins/protovis/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Dendrogram Layout
4 |
5 |
6 |
9 |
10 |
11 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/datablock.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | function DataBlock(numDataCodewords, codewords)
27 | {
28 | this.numDataCodewords = numDataCodewords;
29 | this.codewords = codewords;
30 |
31 | this.__defineGetter__("NumDataCodewords", function()
32 | {
33 | return this.numDataCodewords;
34 | });
35 | this.__defineGetter__("Codewords", function()
36 | {
37 | return this.codewords;
38 | });
39 | }
40 |
41 | DataBlock.getDataBlocks=function(rawCodewords, version, ecLevel)
42 | {
43 |
44 | if (rawCodewords.length != version.TotalCodewords)
45 | {
46 | throw "ArgumentException";
47 | }
48 |
49 | // Figure out the number and size of data blocks used by this version and
50 | // error correction level
51 | var ecBlocks = version.getECBlocksForLevel(ecLevel);
52 |
53 | // First count the total number of data blocks
54 | var totalBlocks = 0;
55 | var ecBlockArray = ecBlocks.getECBlocks();
56 | for (var i = 0; i < ecBlockArray.length; i++)
57 | {
58 | totalBlocks += ecBlockArray[i].Count;
59 | }
60 |
61 | // Now establish DataBlocks of the appropriate size and number of data codewords
62 | var result = new Array(totalBlocks);
63 | var numResultBlocks = 0;
64 | for (var j = 0; j < ecBlockArray.length; j++)
65 | {
66 | var ecBlock = ecBlockArray[j];
67 | for (var i = 0; i < ecBlock.Count; i++)
68 | {
69 | var numDataCodewords = ecBlock.DataCodewords;
70 | var numBlockCodewords = ecBlocks.ECCodewordsPerBlock + numDataCodewords;
71 | result[numResultBlocks++] = new DataBlock(numDataCodewords, new Array(numBlockCodewords));
72 | }
73 | }
74 |
75 | // All blocks have the same amount of data, except that the last n
76 | // (where n may be 0) have 1 more byte. Figure out where these start.
77 | var shorterBlocksTotalCodewords = result[0].codewords.length;
78 | var longerBlocksStartAt = result.length - 1;
79 | while (longerBlocksStartAt >= 0)
80 | {
81 | var numCodewords = result[longerBlocksStartAt].codewords.length;
82 | if (numCodewords == shorterBlocksTotalCodewords)
83 | {
84 | break;
85 | }
86 | longerBlocksStartAt--;
87 | }
88 | longerBlocksStartAt++;
89 |
90 | var shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.ECCodewordsPerBlock;
91 | // The last elements of result may be 1 element longer;
92 | // first fill out as many elements as all of them have
93 | var rawCodewordsOffset = 0;
94 | for (var i = 0; i < shorterBlocksNumDataCodewords; i++)
95 | {
96 | for (var j = 0; j < numResultBlocks; j++)
97 | {
98 | result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];
99 | }
100 | }
101 | // Fill out the last data block in the longer ones
102 | for (var j = longerBlocksStartAt; j < numResultBlocks; j++)
103 | {
104 | result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
105 | }
106 | // Now add in error correction blocks
107 | var max = result[0].codewords.length;
108 | for (var i = shorterBlocksNumDataCodewords; i < max; i++)
109 | {
110 | for (var j = 0; j < numResultBlocks; j++)
111 | {
112 | var iOffset = j < longerBlocksStartAt?i:i + 1;
113 | result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];
114 | }
115 | }
116 | return result;
117 | }
118 |
--------------------------------------------------------------------------------
/js/breadcrumbTrail.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function(window) {
4 | function BreadcrumbTrail() {
5 | this._breadcrumbs = [];
6 | this._selectedBreadcrumbIndex = -1;
7 |
8 | this._containerElement = document.createElement("div");
9 | this._containerElement.className = "breadcrumbTrail";
10 | var self = this;
11 | this._containerElement.addEventListener("click", function (e) {
12 | if (!e.target.classList.contains("breadcrumbTrailItem"))
13 | return;
14 | self._enter(e.target.breadcrumbIndex);
15 | });
16 | }
17 | BreadcrumbTrail.prototype = {
18 | getContainer: function BreadcrumbTrail_getContainer() {
19 | return this._containerElement;
20 | },
21 | /**
22 | * Add a breadcrumb. The breadcrumb parameter is an object with the following
23 | * properties:
24 | * - title: The text that will be shown in the breadcrumb's button.
25 | * - enterCallback: A function that will be called when entering this
26 | * breadcrumb.
27 | */
28 | add: function BreadcrumbTrail_add(breadcrumb) {
29 | for (var i = this._breadcrumbs.length - 1; i > this._selectedBreadcrumbIndex; i--) {
30 | var rearLi = this._breadcrumbs[i];
31 | if (!rearLi.breadcrumbIsTransient)
32 | throw "Can only add new breadcrumbs if after the current one there are only transient ones.";
33 | rearLi.breadcrumbDiscarder.discard();
34 | }
35 | var div = document.createElement("div");
36 | div.className = "breadcrumbTrailItem";
37 | div.textContent = breadcrumb.title;
38 | var index = this._breadcrumbs.length;
39 | div.breadcrumbIndex = index;
40 | div.breadcrumbEnterCallback = breadcrumb.enterCallback;
41 | div.breadcrumbIsTransient = true;
42 | div.style.zIndex = 1000 - index;
43 | this._containerElement.appendChild(div);
44 | this._breadcrumbs.push(div);
45 | if (index == 0)
46 | this._enter(index);
47 | var self = this;
48 | div.breadcrumbDiscarder = {
49 | discard: function () {
50 | if (div.breadcrumbIsTransient) {
51 | self._deleteBeyond(index - 1);
52 | delete div.breadcrumbIsTransient;
53 | delete div.breadcrumbDiscarder;
54 | }
55 | }
56 | };
57 | return div.breadcrumbDiscarder;
58 | },
59 | addAndEnter: function BreadcrumbTrail_addAndEnter(breadcrumb) {
60 | var removalHandle = this.add(breadcrumb);
61 | this._enter(this._breadcrumbs.length - 1);
62 | },
63 | pop : function BreadcrumbTrail_pop() {
64 | if (this._breadcrumbs.length-2 >= 0)
65 | this._enter(this._breadcrumbs.length-2);
66 | },
67 | enterLastItem: function BreadcrumbTrail_enterLastItem(forceSelection) {
68 | this._enter(this._breadcrumbs.length-1, forceSelection);
69 | },
70 | _enter: function BreadcrumbTrail__select(index, forceSelection) {
71 | if (index == this._selectedBreadcrumbIndex)
72 | return;
73 | if (forceSelection) {
74 | gTreeManager.restoreSerializedSelectionSnapshot(forceSelection);
75 | } else {
76 | gTreeManager.saveSelectionSnapshot();
77 | }
78 | var prevSelected = this._breadcrumbs[this._selectedBreadcrumbIndex];
79 | if (prevSelected)
80 | prevSelected.classList.remove("selected");
81 | var li = this._breadcrumbs[index];
82 | if (this === gBreadcrumbTrail && index != 0) {
83 | // Support for back button, disabled until the forward button is implemented.
84 | //var state = {action: "popbreadcrumb",};
85 | //window.history.pushState(state, "Cleopatra");
86 | }
87 | if (!li)
88 | console.log("li at index " + index + " is null!");
89 | delete li.breadcrumbIsTransient;
90 | li.classList.add("selected");
91 | this._deleteBeyond(index);
92 | this._selectedBreadcrumbIndex = index;
93 | li.breadcrumbEnterCallback();
94 | // Add history state
95 | },
96 | _deleteBeyond: function BreadcrumbTrail__deleteBeyond(index) {
97 | while (this._breadcrumbs.length > index + 1) {
98 | this._hide(this._breadcrumbs[index + 1]);
99 | this._breadcrumbs.splice(index + 1, 1);
100 | }
101 | },
102 | _hide: function BreadcrumbTrail__hide(breadcrumb) {
103 | delete breadcrumb.breadcrumbIsTransient;
104 | breadcrumb.classList.add("deleted");
105 | setTimeout(function () {
106 | breadcrumb.parentNode.removeChild(breadcrumb);
107 | }, 1000);
108 | },
109 | };
110 |
111 | window.BreadcrumbTrail = BreadcrumbTrail;
112 | }(this));
--------------------------------------------------------------------------------
/js/qr/jsqrcode/formatinf.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | var FORMAT_INFO_MASK_QR = 0x5412;
27 | var FORMAT_INFO_DECODE_LOOKUP = new Array(new Array(0x5412, 0x00), new Array(0x5125, 0x01), new Array(0x5E7C, 0x02), new Array(0x5B4B, 0x03), new Array(0x45F9, 0x04), new Array(0x40CE, 0x05), new Array(0x4F97, 0x06), new Array(0x4AA0, 0x07), new Array(0x77C4, 0x08), new Array(0x72F3, 0x09), new Array(0x7DAA, 0x0A), new Array(0x789D, 0x0B), new Array(0x662F, 0x0C), new Array(0x6318, 0x0D), new Array(0x6C41, 0x0E), new Array(0x6976, 0x0F), new Array(0x1689, 0x10), new Array(0x13BE, 0x11), new Array(0x1CE7, 0x12), new Array(0x19D0, 0x13), new Array(0x0762, 0x14), new Array(0x0255, 0x15), new Array(0x0D0C, 0x16), new Array(0x083B, 0x17), new Array(0x355F, 0x18), new Array(0x3068, 0x19), new Array(0x3F31, 0x1A), new Array(0x3A06, 0x1B), new Array(0x24B4, 0x1C), new Array(0x2183, 0x1D), new Array(0x2EDA, 0x1E), new Array(0x2BED, 0x1F));
28 | var BITS_SET_IN_HALF_BYTE = new Array(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4);
29 |
30 |
31 | function FormatInformation(formatInfo)
32 | {
33 | this.errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);
34 | this.dataMask = (formatInfo & 0x07);
35 |
36 | this.__defineGetter__("ErrorCorrectionLevel", function()
37 | {
38 | return this.errorCorrectionLevel;
39 | });
40 | this.__defineGetter__("DataMask", function()
41 | {
42 | return this.dataMask;
43 | });
44 | this.GetHashCode=function()
45 | {
46 | return (this.errorCorrectionLevel.ordinal() << 3) | dataMask;
47 | }
48 | this.Equals=function( o)
49 | {
50 | var other = o;
51 | return this.errorCorrectionLevel == other.errorCorrectionLevel && this.dataMask == other.dataMask;
52 | }
53 | }
54 |
55 | FormatInformation.numBitsDiffering=function( a, b)
56 | {
57 | a ^= b; // a now has a 1 bit exactly where its bit differs with b's
58 | // Count bits set quickly with a series of lookups:
59 | return BITS_SET_IN_HALF_BYTE[a & 0x0F] + BITS_SET_IN_HALF_BYTE[(URShift(a, 4) & 0x0F)] + BITS_SET_IN_HALF_BYTE[(URShift(a, 8) & 0x0F)] + BITS_SET_IN_HALF_BYTE[(URShift(a, 12) & 0x0F)] + BITS_SET_IN_HALF_BYTE[(URShift(a, 16) & 0x0F)] + BITS_SET_IN_HALF_BYTE[(URShift(a, 20) & 0x0F)] + BITS_SET_IN_HALF_BYTE[(URShift(a, 24) & 0x0F)] + BITS_SET_IN_HALF_BYTE[(URShift(a, 28) & 0x0F)];
60 | }
61 |
62 | FormatInformation.decodeFormatInformation=function( maskedFormatInfo)
63 | {
64 | var formatInfo = FormatInformation.doDecodeFormatInformation(maskedFormatInfo);
65 | if (formatInfo != null)
66 | {
67 | return formatInfo;
68 | }
69 | // Should return null, but, some QR codes apparently
70 | // do not mask this info. Try again by actually masking the pattern
71 | // first
72 | return FormatInformation.doDecodeFormatInformation(maskedFormatInfo ^ FORMAT_INFO_MASK_QR);
73 | }
74 | FormatInformation.doDecodeFormatInformation=function( maskedFormatInfo)
75 | {
76 | // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing
77 | var bestDifference = 0xffffffff;
78 | var bestFormatInfo = 0;
79 | for (var i = 0; i < FORMAT_INFO_DECODE_LOOKUP.length; i++)
80 | {
81 | var decodeInfo = FORMAT_INFO_DECODE_LOOKUP[i];
82 | var targetInfo = decodeInfo[0];
83 | if (targetInfo == maskedFormatInfo)
84 | {
85 | // Found an exact match
86 | return new FormatInformation(decodeInfo[1]);
87 | }
88 | var bitsDifference = this.numBitsDiffering(maskedFormatInfo, targetInfo);
89 | if (bitsDifference < bestDifference)
90 | {
91 | bestFormatInfo = decodeInfo[1];
92 | bestDifference = bitsDifference;
93 | }
94 | }
95 | // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits
96 | // differing means we found a match
97 | if (bestDifference <= 3)
98 | {
99 | return new FormatInformation(bestFormatInfo);
100 | }
101 | return null;
102 | }
103 |
104 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | QRCODE
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
131 |
132 |
133 |
134 |
135 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/js/FlameGraphUtils.js:
--------------------------------------------------------------------------------
1 | function FlameGraphUtils() {
2 | }
3 |
4 | FlameGraphUtils.prototype.getContainer = function() {
5 | this._container = createElement("div", {
6 | className: "tab",
7 | style: {
8 | background: "white",
9 | height: "100%",
10 | },
11 | });
12 |
13 | this._graph = new FlameGraph(this._container);
14 | this._graph.ready().then(function() {
15 | if (this._data) {
16 | this._graph.setData(this._data);
17 | }
18 | }.bind(this), function() {});
19 |
20 | return this._container;
21 | }
22 |
23 | FlameGraphUtils.prototype.setData = function(samples) {
24 | var FLAME_GRAPH_BLOCK_HEIGHT = 12;
25 | var FLAME_GRAPH_MAX_GAP = 5; // After this gap we consider the sample missed
26 | var PALLETTE_SIZE = 10;
27 | var PALLETTE_HUE_OFFSET = 0;
28 | var PALLETTE_HUE_RANGE = 270;
29 | var PALLETTE_SATURATION = 60;
30 | var PALLETTE_BRIGHTNESS = 75;
31 | var PALLETTE_OPACITY = 0.7;
32 |
33 | var COLOR_PALLETTE = [];
34 | for (var i = 0; i < PALLETTE_SIZE; i++) {
35 | COLOR_PALLETTE.push(
36 | "hsla" +
37 | "(" + ((PALLETTE_HUE_OFFSET + (i / PALLETTE_SIZE * PALLETTE_HUE_RANGE))|0 % 360) +
38 | "," + PALLETTE_SATURATION + "%" +
39 | "," + PALLETTE_BRIGHTNESS + "%" +
40 | "," + PALLETTE_OPACITY +
41 | ")"
42 | );
43 | }
44 |
45 | var out = [];
46 |
47 | // 1. Create a map of colors to arrays, representing buckets of
48 | // blocks inside the flame graph pyramid sharing the same style.
49 | var buckets = {};
50 |
51 | for (var i = 0; i < COLOR_PALLETTE.length; i++) {
52 | var color = COLOR_PALLETTE[i];
53 | buckets[color] = [];
54 | }
55 |
56 | // 2. Populate the buckets by iterating over every frame in every sample.
57 | var prevTime = null;
58 | var prevFrames = [];
59 |
60 | for (var j = 0; j < samples.length; j++) {
61 | var sample = samples[j];
62 | var frames = sample.frames;
63 | var time = sample.time;
64 | if (!time)
65 | continue;
66 |
67 | if (prevTime == null || time - prevTime > FLAME_GRAPH_MAX_GAP) {
68 | prevTime = time;
69 | }
70 |
71 | var frameIndex = 0;
72 |
73 | for (var i = 0; i < frames[0].length; i++) {
74 | var location = gFunctions[frames[0][i]].functionName;
75 | var prevFrame = prevFrames[frameIndex];
76 |
77 | // Frames at the same location and the same depth will be reused.
78 | // If there is a block already created, change its width.
79 | if (prevFrame && prevFrame.srcData.rawLocation == location &&
80 | prevFrame.width + FLAME_GRAPH_MAX_GAP > (time - prevFrame.srcData.startTime)) {
81 | prevFrame.width = (time - prevFrame.srcData.startTime);
82 | }
83 | // Otherwise, create a new block for this frame at this depth,
84 | // using a simple location based salt for picking a color.
85 | else {
86 | var hash = this._getStringHash(location);
87 | var color = COLOR_PALLETTE[hash % PALLETTE_SIZE];
88 | var bucket = buckets[color];
89 |
90 | bucket.push(prevFrames[frameIndex] = {
91 | srcData: { startTime: prevTime, rawLocation: location },
92 | x: prevTime,
93 | y: frameIndex * FLAME_GRAPH_BLOCK_HEIGHT,
94 | width: time - prevTime,
95 | height: FLAME_GRAPH_BLOCK_HEIGHT,
96 | text: location
97 | });
98 | }
99 |
100 | frameIndex++;
101 | }
102 |
103 | // Previous frames at stack depths greater than the current sample's
104 | // maximum need to be nullified. It's nonsensical to reuse them.
105 | for (var i = frameIndex; i < prevFrames.length; i++) {
106 | prevFrames[i] = null;
107 | }
108 |
109 | prevTime = time;
110 | }
111 |
112 | // 3. Convert the buckets into a data source usable by the FlameGraph.
113 | // This is a simple conversion from a Map to an Array.
114 |
115 | for (var i in buckets) {
116 | var color = i;
117 | var blocks = buckets[i];
118 | out.push({ color: color, blocks: blocks });
119 | }
120 |
121 | if (this._graph) {
122 | this._graph.setData(out);
123 | }
124 | this._data = out;
125 |
126 | return out;
127 | }
128 |
129 | /**
130 | * Very dumb hashing of a string. Used to pick colors from a pallette.
131 | *
132 | * @param string input
133 | * @return number
134 | */
135 | FlameGraphUtils.prototype._getStringHash = function(input) {
136 | var STRING_HASH_PRIME1 = 7;
137 | var STRING_HASH_PRIME2 = 31;
138 |
139 | var hash = STRING_HASH_PRIME1;
140 |
141 | for (var i = 0, len = input.length; i < len; i++) {
142 | hash *= STRING_HASH_PRIME2;
143 | hash = (hash + input.charCodeAt(i)) % 65535;
144 | }
145 |
146 | return hash;
147 | };
148 |
--------------------------------------------------------------------------------
/js/sourceView.js:
--------------------------------------------------------------------------------
1 | var escape = document.createElement('textarea');
2 |
3 | function escapeHTML(html) {
4 | escape.innerHTML = html;
5 | return escape.innerHTML;
6 | }
7 |
8 | function unescapeHTML(html) {
9 | escape.innerHTML = html;
10 | return escape.value;
11 | }
12 |
13 | function replaceAll(txt, replace, with_this) {
14 | return txt.replace(new RegExp(replace, 'g'),with_this);
15 | }
16 |
17 | function formatStrSpacing(str) {
18 | str = replaceAll(str, "&", "&");
19 | str = replaceAll(str, "<", "<");
20 | str = replaceAll(str, ">", ">");
21 | str = replaceAll(str, " ", " ");
22 | str = replaceAll(str, "\t", " ");
23 | return str;
24 | }
25 |
26 | function SourceView() {
27 | this._container = document.createElement("div");
28 | this._container.className = "sourceViewContainer";
29 |
30 | this._buttonBar = document.createElement("div");
31 | this._buttonBar.className = "sourceViewTrail";
32 |
33 | this._closeButton = document.createElement("div");
34 | this._closeButton.className = "sourceViewTrailButton";
35 | this._closeButton.innerHTML = "[X] Close";
36 | this._buttonBar.appendChild(this._closeButton);
37 |
38 | this._documentTitle = document.createElement("div");
39 | this._documentTitle.className = "sourceViewTrailItem";
40 | this._documentTitle.innerHTML = "";
41 | this._buttonBar.appendChild(this._documentTitle);
42 |
43 | this._source = null; // String
44 | this._sourceLines = null; // String array
45 | this._sourceLinesObj = null; // String array
46 | this._sourceDiv = document.createElement("div");
47 | this._sourceDiv.className = "sourceContainer";
48 |
49 | var self = this;
50 | this._closeButton.onclick = function() {
51 | self._container.parentNode.removeChild(self._container);
52 | }
53 |
54 | this._container.appendChild(this._buttonBar);
55 | this._container.appendChild(this._sourceDiv);
56 | }
57 |
58 | SourceView.prototype = {
59 | getContainer: function SourceView_getContainer() {
60 | return this._container;
61 | },
62 |
63 | setText: function SourceView_setText(title, text) {
64 | this._source = text;
65 | this._sourceLines = text.split('\n');
66 | this._sourceLinesObj = [];
67 | this._documentTitle.textContent = title;
68 | for (var i = 0; i < this._sourceLines.length; i++) {
69 | var lineCountDiv = document.createElement("span");
70 | lineCountDiv.innerHTML = "";
71 | lineCountDiv.className = "lineCountDiv";
72 | var lineTextDiv = document.createElement("span");
73 | lineTextDiv.innerHTML = formatStrSpacing(this._sourceLines[i]);
74 | lineTextDiv.className = "lineSourceDiv";
75 | var lineBreak = document.createElement("br");
76 | this._sourceDiv.appendChild(lineCountDiv);
77 | this._sourceDiv.appendChild(lineTextDiv);
78 | this._sourceDiv.appendChild(lineBreak);
79 | this._sourceLinesObj.push( [lineCountDiv, lineTextDiv] );
80 | if (false) {
81 | var scrollIntoView = lineTextDiv;
82 | setTimeout(function() {
83 | scrollIntoView.scrollIntoView();
84 | });
85 | lineTextDiv.style.backgroundColor = "rgba(200,0,0,0.5)";
86 | }
87 | }
88 |
89 | },
90 |
91 | setSource: function SourceView_setSource(source) {
92 | source = source || "Script is not available";
93 | this._source = source;
94 | this._sourceLines = source.split('\n');
95 | this._sourceLinesObj = [];
96 | for (var i = 0; i < this._sourceLines.length; i++) {
97 | var lineCountDiv = document.createElement("span");
98 | lineCountDiv.innerHTML = i;
99 | lineCountDiv.className = "lineCountDiv";
100 | var lineTextDiv = document.createElement("span");
101 | lineTextDiv.innerHTML = formatStrSpacing(this._sourceLines[i]);
102 | lineTextDiv.className = "lineSourceDiv";
103 | var lineBreak = document.createElement("br");
104 | this._sourceDiv.appendChild(lineCountDiv);
105 | this._sourceDiv.appendChild(lineTextDiv);
106 | this._sourceDiv.appendChild(lineBreak);
107 | this._sourceLinesObj.push( [lineCountDiv, lineTextDiv] );
108 | if (i == this._scriptLocation.lineInformation - 1) {
109 | var scrollIntoView = lineTextDiv;
110 | setTimeout(function() {
111 | scrollIntoView.scrollIntoView();
112 | });
113 | lineTextDiv.style.backgroundColor = "rgba(200,0,0,0.5)";
114 | }
115 | }
116 | },
117 |
118 | setScriptLocation: function SourceView_setScriptLocation(scriptLocation) {
119 | dump("View source: " + scriptLocation.lineInformation + "\n");
120 | this._documentTitle.textContent = scriptLocation.scriptURI;
121 | this._scriptLocation = scriptLocation;
122 | },
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/js/tabProviders.js:
--------------------------------------------------------------------------------
1 | var gContentScaleID = 0;
2 |
3 | function toFixed(num, fixed) {
4 | fixed = fixed || 0;
5 | fixed = Math.pow(10, fixed);
6 | return Math.floor(num * fixed) / fixed;
7 | }
8 |
9 | function tab_showInstruction(tabName, instruction) {
10 | var currentTab = gTabWidget.getTab(tabName);
11 | if (currentTab && currentTab.isInstruction !== true) {
12 | // We have a real tab, don't set instructions
13 | return;
14 | }
15 |
16 | var container = createElement("div", {
17 | className: "tab",
18 | style: {
19 | background: "white",
20 | height: "100%",
21 | },
22 | textContent: instruction,
23 | });
24 | container.isInstruction = true;
25 | gTabWidget.addTab(tabName, container);
26 | }
27 |
28 |
29 | function tab_showDisplayListDump(displayListDumpLines, title, time) {
30 | time = time || 0;
31 | function parseDisplayListDump() {
32 | var section = null;
33 | displayListParts = {};
34 | for (var i = 0; i < displayListDumpLines.length; i++) {
35 | var line = displayListDumpLines[i].name || displayListDumpLines[i];
36 | if (line.indexOf("Painting --- before optimization") == 0) {
37 | section = "before";
38 | continue;
39 | } else if (line == "Painting --- after optimization:") {
40 | section = "after";
41 | continue;
42 | } else if (line == "Painting --- layer tree:") {
43 | section = "tree";
44 | continue;
45 | }
46 | displayListParts[section] = displayListParts[section] || [];
47 | displayListParts[section].push(line);
48 | }
49 |
50 | return {
51 | before: parseDisplayList(displayListParts["before"]),
52 | after: parseDisplayList(displayListParts["after"]),
53 | tree: parseLayers(displayListParts["tree"]),
54 | };
55 | }
56 | var container = createElement("div", {
57 | style: {
58 | background: "white",
59 | height: "100%",
60 | position: "relative",
61 | },
62 | });
63 |
64 | var titleDiv = createElement("div", {
65 | className: "treeColumnHeader",
66 | style: {
67 | width: "100%",
68 | },
69 | textContent: title + " (near " + time.toFixed(0) + " ms)",
70 | });
71 | container.appendChild(titleDiv);
72 |
73 | var mainDiv = createElement("div", {
74 | style: {
75 | position: "absolute",
76 | top: "16px",
77 | left: "0px",
78 | right: "0px",
79 | bottom: "0px",
80 | },
81 | });
82 | container.appendChild(mainDiv);
83 |
84 | var layerListPane = createElement("div", {
85 | style: {
86 | cssFloat: "left",
87 | height: "100%",
88 | width: "300px",
89 | overflowY: "scroll",
90 | },
91 | });
92 | mainDiv.appendChild(layerListPane);
93 |
94 | var previewContainerDiv = createElement("div", {
95 | style: {
96 | position: "absolute",
97 | left: "300px",
98 | right: "0px",
99 | top: "0px",
100 | bottom: "0px",
101 | padding: "5px",
102 | overflow: "auto",
103 | },
104 | });
105 | mainDiv.appendChild(previewContainerDiv);
106 |
107 | var contentScaleValues = [1, 1.5, 2];
108 |
109 | var contentScaleInput = createElement("span", {
110 | textContent: "Content Scale:"
111 | });
112 | previewContainerDiv.appendChild(contentScaleInput);
113 | var contentScaleInput = createElement("input", {
114 | type: "range",
115 | min: 0,
116 | max: contentScaleValues.length - 1,
117 | value: gContentScaleID,
118 | onchange: function() {
119 | gContentScaleID = parseInt(contentScaleInput.value);
120 | renderPreview();
121 | contentScaleValue.textContent = contentScaleValues[gContentScaleID];
122 | },
123 | });
124 | previewContainerDiv.appendChild(contentScaleInput);
125 | var contentScaleValue = createElement("span", {
126 | textContent: contentScaleValues[gContentScaleID]
127 | });
128 | previewContainerDiv.appendChild(contentScaleValue);
129 |
130 | var previewDiv = createElement("div", {
131 | style: {
132 | position: "absolute",
133 | left: "0px",
134 | right: "0px",
135 | top: "50px",
136 | bottom: "0px",
137 | padding: "5px",
138 | overflow: "auto",
139 | },
140 | });
141 | previewContainerDiv.appendChild(previewDiv);
142 |
143 | var displayListDump = parseDisplayListDump();
144 |
145 | function renderPreview() {
146 | var contentScale = contentScaleValues[gContentScaleID];
147 | previewDiv.innerHTML = "";
148 | layerListPane.innerHTML = "";
149 | populateLayers(displayListDump['tree'], displayListDump['after'], layerListPane, previewDiv, null, contentScale);
150 | }
151 | renderPreview();
152 |
153 | gTabWidget.addTab("DisplayList", container);
154 | gTabWidget.selectTab("DisplayList");
155 | }
156 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/datamask.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | DataMask = {};
27 |
28 | DataMask.forReference = function(reference)
29 | {
30 | if (reference < 0 || reference > 7)
31 | {
32 | throw "System.ArgumentException";
33 | }
34 | return DataMask.DATA_MASKS[reference];
35 | }
36 |
37 | function DataMask000()
38 | {
39 | this.unmaskBitMatrix=function(bits, dimension)
40 | {
41 | for (var i = 0; i < dimension; i++)
42 | {
43 | for (var j = 0; j < dimension; j++)
44 | {
45 | if (this.isMasked(i, j))
46 | {
47 | bits.flip(j, i);
48 | }
49 | }
50 | }
51 | }
52 | this.isMasked=function( i, j)
53 | {
54 | return ((i + j) & 0x01) == 0;
55 | }
56 | }
57 |
58 | function DataMask001()
59 | {
60 | this.unmaskBitMatrix=function(bits, dimension)
61 | {
62 | for (var i = 0; i < dimension; i++)
63 | {
64 | for (var j = 0; j < dimension; j++)
65 | {
66 | if (this.isMasked(i, j))
67 | {
68 | bits.flip(j, i);
69 | }
70 | }
71 | }
72 | }
73 | this.isMasked=function( i, j)
74 | {
75 | return (i & 0x01) == 0;
76 | }
77 | }
78 |
79 | function DataMask010()
80 | {
81 | this.unmaskBitMatrix=function(bits, dimension)
82 | {
83 | for (var i = 0; i < dimension; i++)
84 | {
85 | for (var j = 0; j < dimension; j++)
86 | {
87 | if (this.isMasked(i, j))
88 | {
89 | bits.flip(j, i);
90 | }
91 | }
92 | }
93 | }
94 | this.isMasked=function( i, j)
95 | {
96 | return j % 3 == 0;
97 | }
98 | }
99 |
100 | function DataMask011()
101 | {
102 | this.unmaskBitMatrix=function(bits, dimension)
103 | {
104 | for (var i = 0; i < dimension; i++)
105 | {
106 | for (var j = 0; j < dimension; j++)
107 | {
108 | if (this.isMasked(i, j))
109 | {
110 | bits.flip(j, i);
111 | }
112 | }
113 | }
114 | }
115 | this.isMasked=function( i, j)
116 | {
117 | return (i + j) % 3 == 0;
118 | }
119 | }
120 |
121 | function DataMask100()
122 | {
123 | this.unmaskBitMatrix=function(bits, dimension)
124 | {
125 | for (var i = 0; i < dimension; i++)
126 | {
127 | for (var j = 0; j < dimension; j++)
128 | {
129 | if (this.isMasked(i, j))
130 | {
131 | bits.flip(j, i);
132 | }
133 | }
134 | }
135 | }
136 | this.isMasked=function( i, j)
137 | {
138 | return (((URShift(i, 1)) + (j / 3)) & 0x01) == 0;
139 | }
140 | }
141 |
142 | function DataMask101()
143 | {
144 | this.unmaskBitMatrix=function(bits, dimension)
145 | {
146 | for (var i = 0; i < dimension; i++)
147 | {
148 | for (var j = 0; j < dimension; j++)
149 | {
150 | if (this.isMasked(i, j))
151 | {
152 | bits.flip(j, i);
153 | }
154 | }
155 | }
156 | }
157 | this.isMasked=function( i, j)
158 | {
159 | var temp = i * j;
160 | return (temp & 0x01) + (temp % 3) == 0;
161 | }
162 | }
163 |
164 | function DataMask110()
165 | {
166 | this.unmaskBitMatrix=function(bits, dimension)
167 | {
168 | for (var i = 0; i < dimension; i++)
169 | {
170 | for (var j = 0; j < dimension; j++)
171 | {
172 | if (this.isMasked(i, j))
173 | {
174 | bits.flip(j, i);
175 | }
176 | }
177 | }
178 | }
179 | this.isMasked=function( i, j)
180 | {
181 | var temp = i * j;
182 | return (((temp & 0x01) + (temp % 3)) & 0x01) == 0;
183 | }
184 | }
185 | function DataMask111()
186 | {
187 | this.unmaskBitMatrix=function(bits, dimension)
188 | {
189 | for (var i = 0; i < dimension; i++)
190 | {
191 | for (var j = 0; j < dimension; j++)
192 | {
193 | if (this.isMasked(i, j))
194 | {
195 | bits.flip(j, i);
196 | }
197 | }
198 | }
199 | }
200 | this.isMasked=function( i, j)
201 | {
202 | return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0;
203 | }
204 | }
205 |
206 | DataMask.DATA_MASKS = new Array(new DataMask000(), new DataMask001(), new DataMask010(), new DataMask011(), new DataMask100(), new DataMask101(), new DataMask110(), new DataMask111());
207 |
208 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/grid.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | GridSampler = {};
27 |
28 | GridSampler.checkAndNudgePoints=function( image, points)
29 | {
30 | var width = qrcode.width;
31 | var height = qrcode.height;
32 | // Check and nudge points from start until we see some that are OK:
33 | var nudged = true;
34 | for (var offset = 0; offset < points.length && nudged; offset += 2)
35 | {
36 | var x = Math.floor (points[offset]);
37 | var y = Math.floor( points[offset + 1]);
38 | if (x < - 1 || x > width || y < - 1 || y > height)
39 | {
40 | throw "Error.checkAndNudgePoints ";
41 | }
42 | nudged = false;
43 | if (x == - 1)
44 | {
45 | points[offset] = 0.0;
46 | nudged = true;
47 | }
48 | else if (x == width)
49 | {
50 | points[offset] = width - 1;
51 | nudged = true;
52 | }
53 | if (y == - 1)
54 | {
55 | points[offset + 1] = 0.0;
56 | nudged = true;
57 | }
58 | else if (y == height)
59 | {
60 | points[offset + 1] = height - 1;
61 | nudged = true;
62 | }
63 | }
64 | // Check and nudge points from end:
65 | nudged = true;
66 | for (var offset = points.length - 2; offset >= 0 && nudged; offset -= 2)
67 | {
68 | var x = Math.floor( points[offset]);
69 | var y = Math.floor( points[offset + 1]);
70 | if (x < - 1 || x > width || y < - 1 || y > height)
71 | {
72 | throw "Error.checkAndNudgePoints ";
73 | }
74 | nudged = false;
75 | if (x == - 1)
76 | {
77 | points[offset] = 0.0;
78 | nudged = true;
79 | }
80 | else if (x == width)
81 | {
82 | points[offset] = width - 1;
83 | nudged = true;
84 | }
85 | if (y == - 1)
86 | {
87 | points[offset + 1] = 0.0;
88 | nudged = true;
89 | }
90 | else if (y == height)
91 | {
92 | points[offset + 1] = height - 1;
93 | nudged = true;
94 | }
95 | }
96 | }
97 |
98 |
99 |
100 | GridSampler.sampleGrid3=function( image, dimension, transform)
101 | {
102 | var bits = new BitMatrix(dimension);
103 | var points = new Array(dimension << 1);
104 | for (var y = 0; y < dimension; y++)
105 | {
106 | var max = points.length;
107 | var iValue = y + 0.5;
108 | for (var x = 0; x < max; x += 2)
109 | {
110 | points[x] = (x >> 1) + 0.5;
111 | points[x + 1] = iValue;
112 | }
113 | transform.transformPoints1(points);
114 | // Quick check to see if points transformed to something inside the image;
115 | // sufficient to check the endpoints
116 | GridSampler.checkAndNudgePoints(image, points);
117 | try
118 | {
119 | for (var x = 0; x < max; x += 2)
120 | {
121 | var xpoint = (Math.floor( points[x]) * 4) + (Math.floor( points[x + 1]) * qrcode.width * 4);
122 | var bit = image[Math.floor( points[x])+ qrcode.width* Math.floor( points[x + 1])];
123 | qrcode.imagedata.data[xpoint] = bit?255:0;
124 | qrcode.imagedata.data[xpoint+1] = bit?255:0;
125 | qrcode.imagedata.data[xpoint+2] = 0;
126 | qrcode.imagedata.data[xpoint+3] = 255;
127 | //bits[x >> 1][ y]=bit;
128 | if(bit)
129 | bits.set_Renamed(x >> 1, y);
130 | }
131 | }
132 | catch ( aioobe)
133 | {
134 | // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
135 | // transform gets "twisted" such that it maps a straight line of points to a set of points
136 | // whose endpoints are in bounds, but others are not. There is probably some mathematical
137 | // way to detect this about the transformation that I don't know yet.
138 | // This results in an ugly runtime exception despite our clever checks above -- can't have
139 | // that. We could check each point's coordinates but that feels duplicative. We settle for
140 | // catching and wrapping ArrayIndexOutOfBoundsException.
141 | throw "Error.checkAndNudgePoints";
142 | }
143 | }
144 | return bits;
145 | }
146 |
147 | GridSampler.sampleGridx=function( image, dimension, p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY)
148 | {
149 | var transform = PerspectiveTransform.quadrilateralToQuadrilateral(p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);
150 |
151 | return GridSampler.sampleGrid3(image, dimension, transform);
152 | }
153 |
--------------------------------------------------------------------------------
/js/ui.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function(window) {
4 | function initGlobalVars() {
5 | window.gDebugLog = false;
6 | window.gDebugTrace = false;
7 | window.gLocation = window.location + "";
8 | if (gLocation.indexOf("file:") == 0) {
9 | gDebugLog = true;
10 | gDebugTrace = true;
11 | PROFILERLOG("Turning on logging+tracing since cleopatra is served from the file protocol");
12 | }
13 | window.gFilterChangeCallback = null;
14 | window.gFilterChangeDelay = 1200;
15 |
16 | window.gNumSamples = 0;
17 | window.gMeta = null;
18 | window.gTaskTracer = null;
19 | window.gSymbols = {};
20 | window.gFunctions = {};
21 | window.gResources = {};
22 | window.gThreadsDesc = {};
23 | window.gSelectedThreadId = 0;
24 | window.gHighlightedCallstack = [];
25 | window.gFrameView = null;
26 | window.gTreeManager = null;
27 | window.gCallGraph = null;
28 | window.gMarkerTreeManager = null;
29 | window.gSampleBar = null;
30 | window.gBreadcrumbTrail = null;
31 | window.gHistogramContainer = null;
32 | window.gVideoPane = null;
33 | window.gPluginView = null;
34 | window.gFileList = null;
35 | window.gInfoBar = null;
36 | window.gMainArea = null;
37 | window.gHighlighMovingStack = false;
38 | window.gCurrentlyShownSampleData = null;
39 | window.gSkipSymbols = ["test2", "test1"];
40 | window.gAppendVideoCapture = null;
41 | window.gQueryParamFilterName = null;
42 | window.gRestoreSelection = null;
43 | window.gVideoCapture = null;
44 | window.gReportID = null;
45 | window.gTabWidget = null;
46 | window.gGeckoLogHandler = null;
47 |
48 | window.gImportFromAddonSubreporters = null;
49 |
50 | window.gShowFrames = false;
51 |
52 | window.gInvertCallstack = false;
53 |
54 | window.gMergeUnbranched = false;
55 |
56 | window.gMergeFunctions = true;
57 |
58 | window.gJankOnly = false;
59 | window.gJankThreshold = 50 /* ms */;
60 |
61 | window.gShowMissedSample = false;
62 |
63 | window.gShowPowerInfo = false;
64 | window.gPeakPower = 30; // Watts
65 |
66 | window.gJavascriptOnly = false;
67 |
68 | window.gSampleFilters = [];
69 | };
70 |
71 | // Use for verbose tracing, otherwise use log
72 | window.PROFILERTRACE = function PROFILERTRACE(msg) {
73 | if (gDebugTrace)
74 | PROFILERLOG(msg);
75 | };
76 |
77 | window.PROFILERLOG = function PROFILERLOG(msg) {
78 | if (gDebugLog) {
79 | msg = "Cleo: " + msg;
80 | console.log(msg);
81 | if (window.dump)
82 | window.dump(msg + "\n");
83 | }
84 | };
85 |
86 | window.PROFILERERROR = function PROFILERERROR(msg) {
87 | msg = "Cleo: " + msg;
88 | console.log(msg);
89 | if (window.dump)
90 | window.dump(msg + "\n");
91 | };
92 |
93 | window.removeAllChildren = function removeAllChildren(element) {
94 | while (element.firstChild) {
95 | element.removeChild(element.firstChild);
96 | }
97 | };
98 |
99 | /**
100 | * Dead code
101 | */
102 | window.copyProfile = function copyProfile() {
103 | window.prompt ("Copy to clipboard: Ctrl+C, Enter", document.getElementById("data").value);
104 | };
105 |
106 | /**
107 | * Dead code
108 | */
109 | window.api_toggleMovingStack = function api_toggleMovingStack() {
110 | gHighlighMovingStack = !gHighlighMovingStack;
111 | window.dispatchEvent(new CustomEvent('filters-changed'));
112 | };
113 |
114 | window.getTextData = function getTextData() {
115 | window.data = [];
116 | window.samples = gCurrentlyShownSampleData;
117 | for (window.i = 0; i < samples.length; i++) {
118 | data.push(samples[i].lines.join("\n"));
119 | }
120 | return data.join("\n");
121 | }
122 |
123 | window.comparator_receiveSelection = function comparator_receiveSelection(snapshot, frameData) {
124 | gTreeManager.restoreSerializedSelectionSnapshot(snapshot);
125 | if (frameData)
126 | gTreeManager.highlightFrame(frameData);
127 | AppUI.viewOptionsChanged();
128 | };
129 |
130 | initGlobalVars();
131 | }(this));
132 |
133 | if (!Function.prototype.bind) {
134 | Function.prototype.bind = function(oThis) {
135 | if (typeof this !== 'function') {
136 | // closest thing possible to the ECMAScript 5
137 | // internal IsCallable function
138 | throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
139 | }
140 |
141 | var aArgs = Array.prototype.slice.call(arguments, 1),
142 | fToBind = this,
143 | fNOP = function() {},
144 | fBound = function() {
145 | return fToBind.apply(this instanceof fNOP && oThis
146 | ? this
147 | : oThis,
148 | aArgs.concat(Array.prototype.slice.call(arguments)));
149 | };
150 |
151 | fNOP.prototype = this.prototype;
152 | fBound.prototype = new fNOP();
153 |
154 | return fBound;
155 | };
156 | }
157 |
158 | if (!window.CustomEvent || typeof window.CustomEvent !== 'function') {
159 | var CustomEvent = function(event, params) {
160 | var evt;
161 | params = params || {
162 | bubbles: false,
163 | cancelable: false,
164 | detail: undefined
165 | };
166 | evt = document.createEvent("CustomEvent");
167 | evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
168 | return evt;
169 | };
170 | CustomEvent.prototype = window.Event.prototype;
171 | window.CustomEvent = CustomEvent; // expose definition to window
172 | }
173 |
--------------------------------------------------------------------------------
/css/tree.css:
--------------------------------------------------------------------------------
1 | .treeViewContainer {
2 | -moz-user-select: none;
3 | -webkit-user-select: none;
4 | user-select: none;
5 | cursor: default;
6 | line-height: 16px;
7 | height: 100%;
8 | outline: none; /* override the browser's focus styling */
9 | position: relative;
10 | flex: 1;
11 | }
12 |
13 | .treeHeader {
14 | position: absolute;
15 | top: 0;
16 | right: 0;
17 | left: 0;
18 | height: 16px;
19 | margin: 0;
20 | padding: 0;
21 | }
22 |
23 | .treeColumnHeader {
24 | position: absolute;
25 | display: block;
26 | background: -moz-linear-gradient(#FFF 45%, #EEE 60%);
27 | background: -webkit-linear-gradient(#FFF 45%, #EEE 60%);
28 | background: linear-gradient(#FFF 45%, #EEE 60%);
29 | margin: 0;
30 | padding: 0;
31 | top: 0;
32 | height: 15px;
33 | line-height: 15px;
34 | border: 0 solid #CCC;
35 | border-bottom-width: 1px;
36 | text-indent: 5px;
37 | }
38 |
39 | .treeColumnHeader:not(:last-child) {
40 | border-right-width: 1px;
41 | }
42 |
43 | .treeColumnHeader0 {
44 | left: 0;
45 | width: 86px;
46 | }
47 |
48 | .treeColumnHeader1 {
49 | left: 99px;
50 | width: 35px;
51 | }
52 |
53 | .treeColumnHeader0,
54 | .treeColumnHeader1 {
55 | text-align: right;
56 | padding-right: 12px;
57 | }
58 |
59 | .treeColumnHeader2 {
60 | left: 147px;
61 | width: 20px;
62 | }
63 |
64 | .treeColumnHeader3 {
65 | left: 168px;
66 | right: 0;
67 | }
68 |
69 | .treeViewTreeOuterContainer {
70 | position: absolute;
71 | top: 16px;
72 | left: 0;
73 | right: 0;
74 | bottom: 0;
75 | overflow: auto;
76 | }
77 |
78 | .treeViewNode,
79 | .treeViewTreeInnerContainer {
80 | display: block;
81 | margin: 0;
82 | padding: 0;
83 | }
84 |
85 | .treeViewNode {
86 | white-space: nowrap;
87 | }
88 |
89 | .treeViewTreeInnerContainer {
90 | min-width: intrinsic;
91 | min-width: max-content;
92 | min-width: -moz-max-content;
93 | min-width: -webkit-max-content;
94 | min-height: 100%;
95 | }
96 |
97 | .treeViewTreeInnerContainer {
98 | background: -moz-linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
99 | background: -webkit-linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
100 | background: linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
101 | background-size: 100px 32px;
102 | }
103 | .treeViewTreeInnerContainer>:nth-child(2n+1) {
104 | background-color: white;
105 | }
106 | .treeViewTreeInnerContainer>:nth-child(2n) {
107 | background-color: #f0f5ff;
108 | }
109 |
110 | .treeLine {
111 | background-color: inherit;
112 | }
113 | .rowLabel {
114 | background-color: inherit;
115 | position: -webkit-sticky;
116 | position: sticky;
117 | flex: none;
118 | text-align: right;
119 | }
120 |
121 | .sampleCount {
122 | padding-left: 2px;
123 | padding-right: 3px;
124 | left: 0;
125 | width: 50px;
126 | }
127 |
128 | .samplePercentage {
129 | left: 55px;
130 | padding-right:3px;
131 | width: 40px;
132 | }
133 |
134 | .selfSampleCount {
135 | left: 98px;
136 | width: 45px;
137 | padding-right: 1px;
138 | border: solid #CCC;
139 | border-width: 0 1px;
140 | }
141 |
142 | .resourceIcon {
143 | left: 146px;
144 | width: 18px;
145 | height: 16px;
146 | padding-right: 2px;
147 | border: solid #CCC;
148 | border-width: 0 1px;
149 | background-repeat: no-repeat;
150 | background-size: 14px 14px;
151 | background-position: 3px 1px;
152 | }
153 |
154 | .libraryName {
155 | margin-left: 10px;
156 | color: #999;
157 | }
158 |
159 | .treeViewNode > .treeViewNodeList {
160 | margin-left: 1em;
161 | }
162 |
163 | .treeViewNode.collapsed > .treeViewNodeList {
164 | display: none;
165 | }
166 |
167 | .treeLine {
168 | display: flex;
169 | width: 100%;
170 | }
171 |
172 | .treeLine.selected {
173 | color: black;
174 | background-color: -moz-dialog;
175 | }
176 |
177 | .treeViewContainer:focus .treeLine.selected {
178 | color: highlighttext;
179 | background-color: highlight;
180 | }
181 |
182 | .treeViewContainer:focus .treeLine.selected > .libraryName {
183 | color: #CCC;
184 | }
185 |
186 | .expandCollapseButton,
187 | .focusCallstackButton {
188 | background: none 0 0 no-repeat transparent;
189 | margin: 0;
190 | padding: 0;
191 | border: 0;
192 | width: 16px;
193 | height: 16px;
194 | overflow: hidden;
195 | vertical-align: top;
196 | color: transparent;
197 | }
198 |
199 | .expandCollapseButton {
200 | background-image: url(../images/treetwisty.svg);
201 | }
202 |
203 | .focusCallstackButton {
204 | background-image: url(../images/circlearrow.svg);
205 | margin-left: 5px;
206 | visibility: hidden;
207 | }
208 |
209 | .expandCollapseButton:active:hover,
210 | .focusCallstackButton:active:hover {
211 | background-position: -16px 0;
212 | }
213 |
214 | .treeViewNode.collapsed > .treeLine > .expandCollapseButton {
215 | background-position: 0 -16px;
216 | }
217 |
218 | .treeViewNode.collapsed > .treeLine > .expandCollapseButton:active:hover {
219 | background-position: -16px -16px;
220 | }
221 |
222 | .treeViewContainer:focus .treeLine.selected > .expandCollapseButton,
223 | .treeViewContainer:focus .treeLine.selected > .focusCallstackButton {
224 | background-position: -32px 0;
225 | }
226 |
227 | .treeViewContainer:focus .treeViewNode.collapsed > .treeLine.selected > .expandCollapseButton {
228 | background-position: -32px -16px;
229 | }
230 |
231 | .treeViewContainer:focus .treeLine.selected > .expandCollapseButton:active:hover,
232 | .treeViewContainer:focus .treeLine.selected > .focusCallstackButton:active:hover {
233 | background-position: -48px 0;
234 | }
235 |
236 | .treeViewContainer:focus .treeViewNode.collapsed > .treeLine.selected > .expandCollapseButton:active:hover {
237 | background-position: -48px -16px;
238 | }
239 |
240 | .treeViewNode.leaf > * > .expandCollapseButton {
241 | visibility: hidden;
242 | }
243 |
244 | .treeLine:hover > .focusCallstackButton {
245 | visibility: visible;
246 | }
247 |
--------------------------------------------------------------------------------
/js/fileList.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function(window) {
4 | function loadLocalStorageProfile(profileKey) {
5 | var reporter = AppUI.enterProgressUI();
6 | var subreporters = reporter.addSubreporters({
7 | fileLoading: 1000,
8 | parsing: 1000
9 | });
10 |
11 | gLocalStorage.getProfile(profileKey, function(profile) {
12 | subreporters.fileLoading.finish();
13 | Cleopatra.loadRawProfile(subreporters.parsing, profile, profileKey);
14 | });
15 | subreporters.fileLoading.begin("Reading local storage...");
16 | }
17 |
18 | /**
19 | * FileList is the panel displaying all files.
20 | */
21 | function FileList() {
22 | this._container = document.createElement("ul");
23 | this._container.id = "fileList";
24 | this._selectedFileItem = null;
25 | this._fileItemList = [];
26 | }
27 |
28 | FileList.prototype = {
29 | getContainer: function FileList_getContainer() {
30 | return this._container;
31 | },
32 |
33 | clearFiles: function FileList_clearFiles() {
34 | this.fileItemList = [];
35 | this._selectedFileItem = null;
36 | this._container.innerHTML = "";
37 | },
38 |
39 | loadProfileListFromLocalStorage: function FileList_loadProfileListFromLocalStorage() {
40 | var self = this;
41 | gLocalStorage.getProfileList(function(profileList) {
42 | for (var i = profileList.length - 1; i >= 0; i--) {
43 | (function closure() {
44 | // This only carries info about the profile and the access key to retrieve it.
45 | var profileInfo = profileList[i];
46 | //PROFILERTRACE("Profile list from local storage: " + JSON.stringify(profileInfo));
47 | var dateObj = new Date(profileInfo.date);
48 | var fileEntry = self.addFile(profileInfo, dateObj.toLocaleString(), function fileEntryClick() {
49 | loadLocalStorageProfile(profileInfo.profileKey);
50 | },
51 | function fileRename(newName) {
52 | gLocalStorage.renameProfile(profileInfo.profileKey, newName);
53 | },
54 | function fileDelete() {
55 | gLocalStorage.deleteLocalProfile(profileInfo.profileKey, function deletedProfileCallback() {
56 | self.clearFiles();
57 | gFileList.loadProfileListFromLocalStorage();
58 | });
59 | });
60 | })();
61 | }
62 | });
63 | gLocalStorage.onProfileListChange(function(profileList) {
64 | self.clearFiles();
65 | self.loadProfileListFromLocalStorage();
66 | });
67 | },
68 |
69 | addFile: function FileList_addFile(profileInfo, description, onselect, onrename, ondelete) {
70 | var li = document.createElement("li");
71 |
72 | var fileName;
73 | if (profileInfo.profileKey && profileInfo.profileKey.indexOf("http://profile-store.commondatastorage.googleapis.com/") >= 0) {
74 | fileName = profileInfo.profileKey.substring(54);
75 | fileName = fileName.substring(0, 8) + "..." + fileName.substring(28);
76 | } else {
77 | fileName = profileInfo.name;
78 | }
79 | li.fileName = fileName || "(New Profile)";
80 | li.description = description || "(empty)";
81 |
82 | li.className = "fileListItem";
83 | if (!this._selectedFileItem) {
84 | li.classList.add("selected");
85 | this._selectedFileItem = li;
86 | }
87 |
88 | var self = this;
89 | li.onclick = function() {
90 | self.setSelection(li);
91 | if (onselect)
92 | onselect();
93 | }
94 |
95 | var fileListItemTitleSpan = document.createElement("input");
96 | fileListItemTitleSpan.type = "input";
97 | fileListItemTitleSpan.className = "fileListItemTitle";
98 | fileListItemTitleSpan.value = li.fileName;
99 | fileListItemTitleSpan.onclick = function(event) {
100 | event.stopPropagation();
101 | };
102 | fileListItemTitleSpan.onblur = function() {
103 | if (fileListItemTitleSpan.value != li.fileName) {
104 | onrename(fileListItemTitleSpan.value);
105 | }
106 | };
107 | fileListItemTitleSpan.onkeypress = function(event) {
108 | var code = event.keyCode;
109 | var ENTER_KEYCODE = 13;
110 | if (code == ENTER_KEYCODE) {
111 | fileListItemTitleSpan.blur();
112 | onrename(fileListItemTitleSpan.value);
113 | }
114 | };
115 | li.appendChild(fileListItemTitleSpan);
116 |
117 | var fileListItemDescriptionSpan = document.createElement("span");
118 | fileListItemDescriptionSpan.className = "fileListItemDescription";
119 | fileListItemDescriptionSpan.textContent = li.description;
120 | li.appendChild(fileListItemDescriptionSpan);
121 |
122 | var deleteProfileButton = document.createElement("div");
123 | deleteProfileButton.className = "fileListItemDelete";
124 | deleteProfileButton.title = "Delete the profile from your local cache";
125 | deleteProfileButton.onclick = function(event) {
126 | event.stopPropagation();
127 | ondelete();
128 | };
129 | li.appendChild(deleteProfileButton);
130 |
131 | this._container.appendChild(li);
132 |
133 | this._fileItemList.push(li);
134 |
135 | return li;
136 | },
137 |
138 | setSelection: function FileList_setSelection(fileEntry) {
139 | if (this._selectedFileItem) {
140 | this._selectedFileItem.classList.remove("selected");
141 | }
142 | this._selectedFileItem = fileEntry;
143 | fileEntry.classList.add("selected");
144 | if (this._selectedFileItem.onselect)
145 | this._selectedFileItem.onselect();
146 | },
147 |
148 | profileParsingFinished: function FileList_profileParsingFinished() {
149 | //this._container.querySelector(".fileListItemTitle").textContent = "Current Profile";
150 | //this._container.querySelector(".fileListItemDescription").textContent = gNumSamples + " Samples";
151 | }
152 | };
153 |
154 | window.FileList = FileList;
155 | }(this));
156 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/rsdecoder.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | function ReedSolomonDecoder(field)
27 | {
28 | this.field = field;
29 | this.decode=function(received, twoS)
30 | {
31 | var poly = new GF256Poly(this.field, received);
32 | var syndromeCoefficients = new Array(twoS);
33 | for(var i=0;i= b's
70 | if (a.Degree < b.Degree)
71 | {
72 | var temp = a;
73 | a = b;
74 | b = temp;
75 | }
76 |
77 | var rLast = a;
78 | var r = b;
79 | var sLast = this.field.One;
80 | var s = this.field.Zero;
81 | var tLast = this.field.Zero;
82 | var t = this.field.One;
83 |
84 | // Run Euclidean algorithm until r's degree is less than R/2
85 | while (r.Degree >= Math.floor(R / 2))
86 | {
87 | var rLastLast = rLast;
88 | var sLastLast = sLast;
89 | var tLastLast = tLast;
90 | rLast = r;
91 | sLast = s;
92 | tLast = t;
93 |
94 | // Divide rLastLast by rLast, with quotient in q and remainder in r
95 | if (rLast.Zero)
96 | {
97 | // Oops, Euclidean algorithm already terminated?
98 | throw "r_{i-1} was zero";
99 | }
100 | r = rLastLast;
101 | var q = this.field.Zero;
102 | var denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree);
103 | var dltInverse = this.field.inverse(denominatorLeadingTerm);
104 | while (r.Degree >= rLast.Degree && !r.Zero)
105 | {
106 | var degreeDiff = r.Degree - rLast.Degree;
107 | var scale = this.field.multiply(r.getCoefficient(r.Degree), dltInverse);
108 | q = q.addOrSubtract(this.field.buildMonomial(degreeDiff, scale));
109 | r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));
110 | //r.EXE();
111 | }
112 |
113 | s = q.multiply1(sLast).addOrSubtract(sLastLast);
114 | t = q.multiply1(tLast).addOrSubtract(tLastLast);
115 | }
116 |
117 | var sigmaTildeAtZero = t.getCoefficient(0);
118 | if (sigmaTildeAtZero == 0)
119 | {
120 | throw "ReedSolomonException sigmaTilde(0) was zero";
121 | }
122 |
123 | var inverse = this.field.inverse(sigmaTildeAtZero);
124 | var sigma = t.multiply2(inverse);
125 | var omega = r.multiply2(inverse);
126 | return new Array(sigma, omega);
127 | }
128 | this.findErrorLocations=function( errorLocator)
129 | {
130 | // This is a direct application of Chien's search
131 | var numErrors = errorLocator.Degree;
132 | if (numErrors == 1)
133 | {
134 | // shortcut
135 | return new Array(errorLocator.getCoefficient(1));
136 | }
137 | var result = new Array(numErrors);
138 | var e = 0;
139 | for (var i = 1; i < 256 && e < numErrors; i++)
140 | {
141 | if (errorLocator.evaluateAt(i) == 0)
142 | {
143 | result[e] = this.field.inverse(i);
144 | e++;
145 | }
146 | }
147 | if (e != numErrors)
148 | {
149 | throw "Error locator degree does not match number of roots";
150 | }
151 | return result;
152 | }
153 | this.findErrorMagnitudes=function( errorEvaluator, errorLocations, dataMatrix)
154 | {
155 | // This is directly applying Forney's Formula
156 | var s = errorLocations.length;
157 | var result = new Array(s);
158 | for (var i = 0; i < s; i++)
159 | {
160 | var xiInverse = this.field.inverse(errorLocations[i]);
161 | var denominator = 1;
162 | for (var j = 0; j < s; j++)
163 | {
164 | if (i != j)
165 | {
166 | denominator = this.field.multiply(denominator, GF256.addOrSubtract(1, this.field.multiply(errorLocations[j], xiInverse)));
167 | }
168 | }
169 | result[i] = this.field.multiply(errorEvaluator.evaluateAt(xiInverse), this.field.inverse(denominator));
170 | // Thanks to sanfordsquires for this fix:
171 | if (dataMatrix)
172 | {
173 | result[i] = this.field.multiply(result[i], xiInverse);
174 | }
175 | }
176 | return result;
177 | }
178 | }
--------------------------------------------------------------------------------
/qunit/qunit-1.16.0.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * QUnit 1.16.0
3 | * http://qunitjs.com/
4 | *
5 | * Copyright 2006, 2014 jQuery Foundation and other contributors
6 | * Released under the MIT license
7 | * http://jquery.org/license
8 | *
9 | * Date: 2014-12-03T16:32Z
10 | */
11 |
12 | /** Font Family and Sizes */
13 |
14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
16 | }
17 |
18 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
19 | #qunit-tests { font-size: smaller; }
20 |
21 |
22 | /** Resets */
23 |
24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
25 | margin: 0;
26 | padding: 0;
27 | }
28 |
29 |
30 | /** Header */
31 |
32 | #qunit-header {
33 | padding: 0.5em 0 0.5em 1em;
34 |
35 | color: #8699A4;
36 | background-color: #0D3349;
37 |
38 | font-size: 1.5em;
39 | line-height: 1em;
40 | font-weight: 400;
41 |
42 | border-radius: 5px 5px 0 0;
43 | }
44 |
45 | #qunit-header a {
46 | text-decoration: none;
47 | color: #C2CCD1;
48 | }
49 |
50 | #qunit-header a:hover,
51 | #qunit-header a:focus {
52 | color: #FFF;
53 | }
54 |
55 | #qunit-testrunner-toolbar label {
56 | display: inline-block;
57 | padding: 0 0.5em 0 0.1em;
58 | }
59 |
60 | #qunit-banner {
61 | height: 5px;
62 | }
63 |
64 | #qunit-testrunner-toolbar {
65 | padding: 0.5em 1em 0.5em 1em;
66 | color: #5E740B;
67 | background-color: #EEE;
68 | overflow: hidden;
69 | }
70 |
71 | #qunit-userAgent {
72 | padding: 0.5em 1em 0.5em 1em;
73 | background-color: #2B81AF;
74 | color: #FFF;
75 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
76 | }
77 |
78 | #qunit-modulefilter-container {
79 | float: right;
80 | }
81 |
82 | /** Tests: Pass/Fail */
83 |
84 | #qunit-tests {
85 | list-style-position: inside;
86 | }
87 |
88 | #qunit-tests li {
89 | padding: 0.4em 1em 0.4em 1em;
90 | border-bottom: 1px solid #FFF;
91 | list-style-position: inside;
92 | }
93 |
94 | #qunit-tests > li {
95 | display: none;
96 | }
97 |
98 | #qunit-tests li.pass, #qunit-tests li.running, #qunit-tests li.fail {
99 | display: list-item;
100 | }
101 |
102 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
103 | display: none;
104 | }
105 |
106 | #qunit-tests li strong {
107 | cursor: pointer;
108 | }
109 |
110 | #qunit-tests li.skipped strong {
111 | cursor: default;
112 | }
113 |
114 | #qunit-tests li a {
115 | padding: 0.5em;
116 | color: #C2CCD1;
117 | text-decoration: none;
118 | }
119 | #qunit-tests li a:hover,
120 | #qunit-tests li a:focus {
121 | color: #000;
122 | }
123 |
124 | #qunit-tests li .runtime {
125 | float: right;
126 | font-size: smaller;
127 | }
128 |
129 | .qunit-assert-list {
130 | margin-top: 0.5em;
131 | padding: 0.5em;
132 |
133 | background-color: #FFF;
134 |
135 | border-radius: 5px;
136 | }
137 |
138 | .qunit-collapsed {
139 | display: none;
140 | }
141 |
142 | #qunit-tests table {
143 | border-collapse: collapse;
144 | margin-top: 0.2em;
145 | }
146 |
147 | #qunit-tests th {
148 | text-align: right;
149 | vertical-align: top;
150 | padding: 0 0.5em 0 0;
151 | }
152 |
153 | #qunit-tests td {
154 | vertical-align: top;
155 | }
156 |
157 | #qunit-tests pre {
158 | margin: 0;
159 | white-space: pre-wrap;
160 | word-wrap: break-word;
161 | }
162 |
163 | #qunit-tests del {
164 | background-color: #E0F2BE;
165 | color: #374E0C;
166 | text-decoration: none;
167 | }
168 |
169 | #qunit-tests ins {
170 | background-color: #FFCACA;
171 | color: #500;
172 | text-decoration: none;
173 | }
174 |
175 | /*** Test Counts */
176 |
177 | #qunit-tests b.counts { color: #000; }
178 | #qunit-tests b.passed { color: #5E740B; }
179 | #qunit-tests b.failed { color: #710909; }
180 |
181 | #qunit-tests li li {
182 | padding: 5px;
183 | background-color: #FFF;
184 | border-bottom: none;
185 | list-style-position: inside;
186 | }
187 |
188 | /*** Passing Styles */
189 |
190 | #qunit-tests li li.pass {
191 | color: #3C510C;
192 | background-color: #FFF;
193 | border-left: 10px solid #C6E746;
194 | }
195 |
196 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
197 | #qunit-tests .pass .test-name { color: #366097; }
198 |
199 | #qunit-tests .pass .test-actual,
200 | #qunit-tests .pass .test-expected { color: #999; }
201 |
202 | #qunit-banner.qunit-pass { background-color: #C6E746; }
203 |
204 | /*** Failing Styles */
205 |
206 | #qunit-tests li li.fail {
207 | color: #710909;
208 | background-color: #FFF;
209 | border-left: 10px solid #EE5757;
210 | white-space: pre;
211 | }
212 |
213 | #qunit-tests > li:last-child {
214 | border-radius: 0 0 5px 5px;
215 | }
216 |
217 | #qunit-tests .fail { color: #000; background-color: #EE5757; }
218 | #qunit-tests .fail .test-name,
219 | #qunit-tests .fail .module-name { color: #000; }
220 |
221 | #qunit-tests .fail .test-actual { color: #EE5757; }
222 | #qunit-tests .fail .test-expected { color: #008000; }
223 |
224 | #qunit-banner.qunit-fail { background-color: #EE5757; }
225 |
226 | /*** Skipped tests */
227 |
228 | #qunit-tests .skipped {
229 | background-color: #EBECE9;
230 | }
231 |
232 | #qunit-tests .qunit-skipped-label {
233 | background-color: #F4FF77;
234 | display: inline-block;
235 | font-style: normal;
236 | color: #366097;
237 | line-height: 1.8em;
238 | padding: 0 0.5em;
239 | margin: -0.4em 0.4em -0.4em 0;
240 | }
241 |
242 | /** Result */
243 |
244 | #qunit-testresult {
245 | padding: 0.5em 1em 0.5em 1em;
246 |
247 | color: #2B81AF;
248 | background-color: #D2E0E6;
249 |
250 | border-bottom: 1px solid #FFF;
251 | }
252 | #qunit-testresult .module-name {
253 | font-weight: 700;
254 | }
255 |
256 | /** Fixture */
257 |
258 | #qunit-fixture {
259 | position: absolute;
260 | top: -10000px;
261 | left: -10000px;
262 | width: 1000px;
263 | height: 1000px;
264 | }
265 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/bmparser.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | function BitMatrixParser(bitMatrix)
27 | {
28 | var dimension = bitMatrix.Dimension;
29 | if (dimension < 21 || (dimension & 0x03) != 1)
30 | {
31 | throw "Error BitMatrixParser";
32 | }
33 | this.bitMatrix = bitMatrix;
34 | this.parsedVersion = null;
35 | this.parsedFormatInfo = null;
36 |
37 | this.copyBit=function( i, j, versionBits)
38 | {
39 | return this.bitMatrix.get_Renamed(i, j)?(versionBits << 1) | 0x1:versionBits << 1;
40 | }
41 |
42 | this.readFormatInformation=function()
43 | {
44 | if (this.parsedFormatInfo != null)
45 | {
46 | return this.parsedFormatInfo;
47 | }
48 |
49 | // Read top-left format info bits
50 | var formatInfoBits = 0;
51 | for (var i = 0; i < 6; i++)
52 | {
53 | formatInfoBits = this.copyBit(i, 8, formatInfoBits);
54 | }
55 | // .. and skip a bit in the timing pattern ...
56 | formatInfoBits = this.copyBit(7, 8, formatInfoBits);
57 | formatInfoBits = this.copyBit(8, 8, formatInfoBits);
58 | formatInfoBits = this.copyBit(8, 7, formatInfoBits);
59 | // .. and skip a bit in the timing pattern ...
60 | for (var j = 5; j >= 0; j--)
61 | {
62 | formatInfoBits = this.copyBit(8, j, formatInfoBits);
63 | }
64 |
65 | this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits);
66 | if (this.parsedFormatInfo != null)
67 | {
68 | return this.parsedFormatInfo;
69 | }
70 |
71 | // Hmm, failed. Try the top-right/bottom-left pattern
72 | var dimension = this.bitMatrix.Dimension;
73 | formatInfoBits = 0;
74 | var iMin = dimension - 8;
75 | for (var i = dimension - 1; i >= iMin; i--)
76 | {
77 | formatInfoBits = this.copyBit(i, 8, formatInfoBits);
78 | }
79 | for (var j = dimension - 7; j < dimension; j++)
80 | {
81 | formatInfoBits = this.copyBit(8, j, formatInfoBits);
82 | }
83 |
84 | this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits);
85 | if (this.parsedFormatInfo != null)
86 | {
87 | return this.parsedFormatInfo;
88 | }
89 | throw "Error readFormatInformation";
90 | }
91 | this.readVersion=function()
92 | {
93 |
94 | if (this.parsedVersion != null)
95 | {
96 | return this.parsedVersion;
97 | }
98 |
99 | var dimension = this.bitMatrix.Dimension;
100 |
101 | var provisionalVersion = (dimension - 17) >> 2;
102 | if (provisionalVersion <= 6)
103 | {
104 | return Version.getVersionForNumber(provisionalVersion);
105 | }
106 |
107 | // Read top-right version info: 3 wide by 6 tall
108 | var versionBits = 0;
109 | var ijMin = dimension - 11;
110 | for (var j = 5; j >= 0; j--)
111 | {
112 | for (var i = dimension - 9; i >= ijMin; i--)
113 | {
114 | versionBits = this.copyBit(i, j, versionBits);
115 | }
116 | }
117 |
118 | this.parsedVersion = Version.decodeVersionInformation(versionBits);
119 | if (this.parsedVersion != null && this.parsedVersion.DimensionForVersion == dimension)
120 | {
121 | return this.parsedVersion;
122 | }
123 |
124 | // Hmm, failed. Try bottom left: 6 wide by 3 tall
125 | versionBits = 0;
126 | for (var i = 5; i >= 0; i--)
127 | {
128 | for (var j = dimension - 9; j >= ijMin; j--)
129 | {
130 | versionBits = this.copyBit(i, j, versionBits);
131 | }
132 | }
133 |
134 | this.parsedVersion = Version.decodeVersionInformation(versionBits);
135 | if (this.parsedVersion != null && this.parsedVersion.DimensionForVersion == dimension)
136 | {
137 | return this.parsedVersion;
138 | }
139 | throw "Error readVersion";
140 | }
141 | this.readCodewords=function()
142 | {
143 |
144 | var formatInfo = this.readFormatInformation();
145 | var version = this.readVersion();
146 |
147 | // Get the data mask for the format used in this QR Code. This will exclude
148 | // some bits from reading as we wind through the bit matrix.
149 | var dataMask = DataMask.forReference( formatInfo.DataMask);
150 | var dimension = this.bitMatrix.Dimension;
151 | dataMask.unmaskBitMatrix(this.bitMatrix, dimension);
152 |
153 | var functionPattern = version.buildFunctionPattern();
154 |
155 | var readingUp = true;
156 | var result = new Array(version.TotalCodewords);
157 | var resultOffset = 0;
158 | var currentByte = 0;
159 | var bitsRead = 0;
160 | // Read columns in pairs, from right to left
161 | for (var j = dimension - 1; j > 0; j -= 2)
162 | {
163 | if (j == 6)
164 | {
165 | // Skip whole column with vertical alignment pattern;
166 | // saves time and makes the other code proceed more cleanly
167 | j--;
168 | }
169 | // Read alternatingly from bottom to top then top to bottom
170 | for (var count = 0; count < dimension; count++)
171 | {
172 | var i = readingUp?dimension - 1 - count:count;
173 | for (var col = 0; col < 2; col++)
174 | {
175 | // Ignore bits covered by the function pattern
176 | if (!functionPattern.get_Renamed(j - col, i))
177 | {
178 | // Read a bit
179 | bitsRead++;
180 | currentByte <<= 1;
181 | if (this.bitMatrix.get_Renamed(j - col, i))
182 | {
183 | currentByte |= 1;
184 | }
185 | // If we've made a whole byte, save it off
186 | if (bitsRead == 8)
187 | {
188 | result[resultOffset++] = currentByte;
189 | bitsRead = 0;
190 | currentByte = 0;
191 | }
192 | }
193 | }
194 | }
195 | readingUp ^= true; // readingUp = !readingUp; // switch directions
196 | }
197 | if (resultOffset != version.TotalCodewords)
198 | {
199 | throw "Error readCodewords";
200 | }
201 | return result;
202 | }
203 | }
--------------------------------------------------------------------------------
/js/videoPane.js:
--------------------------------------------------------------------------------
1 | function VideoPane(videoCapture, frameStart) {
2 | var qrScripts = [
3 | "grid.js",
4 | "version.js",
5 | "detector.js",
6 | "formatinf.js",
7 | "errorlevel.js",
8 | "bitmat.js",
9 | "datablock.js",
10 | "bmparser.js",
11 | "datamask.js",
12 | "rsdecoder.js",
13 | "gf256poly.js",
14 | "gf256.js",
15 | "decoder.js",
16 | "qrcode.js",
17 | "findpat.js",
18 | "alignpat.js",
19 | "databr.js"
20 | ];
21 |
22 | for (var i = 0; i < qrScripts.length; i++) {
23 | var scriptFile = qrScripts[i];
24 | var js = document.createElement("script");
25 | js.type = "text/javascript";
26 | js.src = "js/qr/jsqrcode/"+ scriptFile;
27 | document.body.appendChild(js);
28 | }
29 |
30 | this._container = document.createElement("div");
31 | this._container.className = "videoPane";
32 | this._onTimeChange = null;
33 |
34 | this._video = document.createElement("video");
35 | this._video.className = "video";
36 | //this._video.width = 480;
37 | this._video.crossOrigin = 'anonymous';
38 | this._video.crossorigin = 'anonymous';
39 | this._video.addEventListener("play", function() {
40 | //this.playbackRate = 0.05;
41 | });
42 | this._container.appendChild(this._video);
43 |
44 | this._video.addEventListener("loadeddata", function canplayfunc() {
45 | self._video.currentTime += 0.1;
46 | self._video.removeEventListener("loadeddata", canplayfunc);
47 | });
48 | this._videoUrl = videoCapture.src;
49 | this._video.src = this._videoUrl;
50 |
51 | this._canvas = document.createElement("canvas");
52 | this._canvas.id = "qr-canvas";
53 | this._canvas.style.display = "none";
54 | this._frameStart = frameStart;
55 | this._syncPoint = {};
56 | document.body.appendChild(this._canvas);
57 |
58 | this._busyCover = document.createElement("div");
59 | this._busyCover.className = "busyCover";
60 | this._busyCover.id = "videoCover";
61 | this._container.appendChild(this._busyCover);
62 |
63 | // When this is true we're reading back the video stream
64 | this._reading = true;
65 | this._busyCover.classList.add("busy");
66 | var self = this;
67 | self._video.addEventListener("seeked", function seekedfunc() {
68 | if (self._reading) {
69 | self.getCurrentFrameNumber();
70 | var prevTime = self._video.currentTime;
71 | self._video.currentTime += 0.016 * 5;
72 | if (self._video.currentTime == prevTime) {
73 | self._busyCover.classList.remove("busy");
74 | self._reading = false;
75 | self._video.controls = "controls";
76 | self._lockTimeToBound();
77 | }
78 | } else {
79 | console.log("seeked");
80 | }
81 | });
82 |
83 | // When we get a time update we fire a callback because
84 | // the updated frame might not have been ready.
85 | this._timeUpdateCallback = null;
86 | }
87 |
88 | VideoPane.prototype = {
89 | getContainer: function VideoPane_getContainer() {
90 | return this._container;
91 | },
92 | _lockTimeToBound: function() {
93 | if (this._reading)
94 | return;
95 | var newTime = null;
96 | if (this._video.currentTime * 1000 < this.minBound) {
97 | newTime = this.minBound / 1000;
98 | } else if (this._video.currentTime * 1000 > this.maxBound) {
99 | newTime = this.maxBound / 1000;
100 | if (this._video.paused == false) {
101 | // loop back
102 | newTime = this.minBound / 1000;
103 | }
104 | }
105 | if (newTime && newTime >= 0 && newTime < this._video.duration) {
106 | this._video.currentTime = newTime;
107 | }
108 | },
109 | onTimeChange: function VideoPane_onTimeChange(callback) {
110 | var self = this;
111 | this._video.addEventListener("timeupdate", function() {
112 | if (self._reading)
113 | return;
114 | self._lockTimeToBound();
115 | callback(self._video);
116 | });
117 | },
118 | getCurrentFrameNumber: function VideoPane_getCurrentFrameNumber() {
119 | var self = this;
120 | var number = null;
121 |
122 | if (this._canvas.width != this._video.videoWidth ||
123 | this._canvas.height != this._video.videoHeight) {
124 | this._canvas.width = this._video.videoWidth;
125 | this._canvas.height = this._video.videoHeight;
126 | }
127 |
128 | var context = this._canvas.getContext("2d");
129 | context.drawImage(this._video, 0, 0, this._canvas.width, this._canvas.height);
130 |
131 | // TODO patch library to accept an element
132 | qrcode.callback = function(data) {
133 | number = parseInt(data);
134 | self.foundFrame(number, self._frameStart[number], self._video.currentTime * 1000);
135 | }
136 | try {
137 | qrcode.decode();
138 | } catch (e) {
139 | }
140 | return number;
141 | },
142 | setBoundaries: function VideoPane_setBounadries(boundaries) {
143 | var min = boundaries.min;
144 | var max = boundaries.max;
145 |
146 | var startStr = "";
147 | var endStr = "";
148 |
149 | if (min != min) {
150 | this.minBound = null;
151 | } else {
152 | this.minBound = this.getApproxVideoTime(min);
153 | startStr = this.minBound / 1000;
154 | }
155 | if (max != max) {
156 | this.maxBound = null;
157 | } else {
158 | this.maxBound = this.getApproxVideoTime(max);
159 | endStr = this.maxBound / 1000;
160 | }
161 |
162 | console.log("Bound: " + this.minBound + " , " + this.maxBound);
163 | this._lockTimeToBound();
164 | },
165 | foundFrame: function VideoPane_foundFrame(frame, profileTime, videoTime) {
166 | profileTime = Math.round(profileTime);
167 | videoTime = Math.round(videoTime);
168 | this._syncPoint[profileTime] = {
169 | videoTime: videoTime,
170 | profileTime: profileTime,
171 | frame: frame,
172 | };
173 | console.log("Found frame: " + JSON.stringify(this._syncPoint));
174 | },
175 | _getTimeOffset: function() {
176 | var self = this;
177 |
178 | var values = Object.keys(this._syncPoint);
179 | values.sort(function(a,b) {
180 | return self._syncPoint[a].videoTime - self._syncPoint[b].videoTime;
181 | });
182 | var currFrame = null;
183 | var frameReading = [];
184 | for (var i = 0; i < values.length; i++) {
185 | var entry = this._syncPoint[values[i]];
186 | if (currFrame != entry.frame) {
187 | currFrame = entry.frame;
188 | frameReading.push(entry);
189 | }
190 | }
191 | function prune() {
192 | for (var i = frameReading.length - 1; i >= 0; i--) {
193 | for (var j = i - 1; j >= 0; j--) {
194 | if (frameReading[i].frame < frameReading[j].frame) {
195 | frameReading = frameReading.slice(i);
196 | return;
197 | }
198 | }
199 | }
200 | }
201 | // Prune data we wrapped around
202 | prune();
203 |
204 | if (frameReading.length < 1) {
205 | return null;
206 | }
207 |
208 | var offset = frameReading[frameReading.length - 1].videoTime - frameReading[frameReading.length - 1].profileTime;
209 | return offset;
210 | },
211 | getApproxVideoTime: function(profileTime) {
212 | return profileTime + this._getTimeOffset();
213 | },
214 | getApproxTime: function VideoFrame_getApproxTime(videoTime) {
215 | videoTime = videoTime | (this._video.currentTime * 1000);
216 | return videoTime - this._getTimeOffset();
217 | },
218 | };
219 |
220 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/gf256poly.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | function GF256Poly(field, coefficients)
27 | {
28 | if (coefficients == null || coefficients.length == 0)
29 | {
30 | throw "System.ArgumentException";
31 | }
32 | this.field = field;
33 | var coefficientsLength = coefficients.length;
34 | if (coefficientsLength > 1 && coefficients[0] == 0)
35 | {
36 | // Leading term must be non-zero for anything except the constant polynomial "0"
37 | var firstNonZero = 1;
38 | while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0)
39 | {
40 | firstNonZero++;
41 | }
42 | if (firstNonZero == coefficientsLength)
43 | {
44 | this.coefficients = field.Zero.coefficients;
45 | }
46 | else
47 | {
48 | this.coefficients = new Array(coefficientsLength - firstNonZero);
49 | for(var i=0;i largerCoefficients.length)
121 | {
122 | var temp = smallerCoefficients;
123 | smallerCoefficients = largerCoefficients;
124 | largerCoefficients = temp;
125 | }
126 | var sumDiff = new Array(largerCoefficients.length);
127 | var lengthDiff = largerCoefficients.length - smallerCoefficients.length;
128 | // Copy high-order terms only found in higher-degree polynomial's coefficients
129 | //Array.Copy(largerCoefficients, 0, sumDiff, 0, lengthDiff);
130 | for(var ci=0;ci= other.Degree && !remainder.Zero)
219 | {
220 | var degreeDifference = remainder.Degree - other.Degree;
221 | var scale = this.field.multiply(remainder.getCoefficient(remainder.Degree), inverseDenominatorLeadingTerm);
222 | var term = other.multiplyByMonomial(degreeDifference, scale);
223 | var iterationQuotient = this.field.buildMonomial(degreeDifference, scale);
224 | quotient = quotient.addOrSubtract(iterationQuotient);
225 | remainder = remainder.addOrSubtract(term);
226 | }
227 |
228 | return new Array(quotient, remainder);
229 | }
230 | }
--------------------------------------------------------------------------------
/js/ProgressReporter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ProgressReporter
3 | *
4 | * This class is used by long-winded tasks to report progress to observers.
5 | * If a task has subtasks that want to report their own progress, these
6 | * subtasks can have their own progress reporters which are hooked up to the
7 | * parent progress reporter, resulting in a tree structure. A parent progress
8 | * reporter will calculate its progress value as a weighted sum of its
9 | * subreporters' progress values.
10 | *
11 | * A progress reporter has a state, an action, and a progress value.
12 | *
13 | * - state is one of STATE_WAITING, STATE_DOING and STATE_FINISHED.
14 | * - action is a string that describes the current task.
15 | * - progress is the progress value as a number between 0 and 1, or NaN if
16 | * indeterminate.
17 | *
18 | * A progress reporter starts out in the WAITING state. The DOING state is
19 | * entered with the begin method which also sets the action. While the task is
20 | * executing, the progress value can be updated with the setProgress method.
21 | * When a task has finished, it can call the finish method which is just a
22 | * shorthand for setProgress(1); this will set the state to FINISHED.
23 | *
24 | * Progress observers can be added with the addListener method which takes a
25 | * function callback. Whenever the progress value or state change, all
26 | * listener callbacks will be called with the progress reporter object. The
27 | * observer can get state, progress value and action by calling the getter
28 | * methods getState(), getProgress() and getAction().
29 | *
30 | * Creating child progress reporters for subtasks can be done with the
31 | * addSubreporter(s) methods. If a progress reporter has subreporters, normal
32 | * progress report functions (setProgress and finish) can no longer be called.
33 | * Instead, the parent reporter will listen to progress changes on its
34 | * subreporters and update its state automatically, and then notify its own
35 | * listeners.
36 | * When adding a subreporter, you are expected to provide an estimated
37 | * duration for the subtask. This value will be used as a weight when
38 | * calculating the progress of the parent reporter.
39 | */
40 |
41 | const gDebugExpectedDurations = false;
42 |
43 | function ProgressReporter() {
44 | this._observers = [];
45 | this._subreporters = [];
46 | this._subreporterExpectedDurationsSum = 0;
47 | this._progress = 0;
48 | this._state = ProgressReporter.STATE_WAITING;
49 | this._action = "";
50 | }
51 |
52 | ProgressReporter.STATE_WAITING = 0;
53 | ProgressReporter.STATE_DOING = 1;
54 | ProgressReporter.STATE_FINISHED = 2;
55 |
56 | ProgressReporter.prototype = {
57 | getProgress: function () {
58 | return this._progress;
59 | },
60 | getState: function () {
61 | return this._state;
62 | },
63 | setAction: function (action) {
64 | this._action = action;
65 | this._reportProgress();
66 | },
67 | getAction: function () {
68 | switch (this._state) {
69 | case ProgressReporter.STATE_WAITING:
70 | return "Waiting for preceding tasks to finish...";
71 | case ProgressReporter.STATE_DOING:
72 | return this._action;
73 | case ProgressReporter.STATE_FINISHED:
74 | return "Finished.";
75 | default:
76 | throw "Broken state";
77 | }
78 | },
79 | addListener: function (callback) {
80 | this._observers.push(callback);
81 | },
82 | addSubreporter: function (expectedDuration) {
83 | this._subreporterExpectedDurationsSum += expectedDuration;
84 | var subreporter = new ProgressReporter();
85 | var self = this;
86 | subreporter.addListener(function (progress) {
87 | self._recalculateProgressFromSubreporters();
88 | self._recalculateStateAndActionFromSubreporters();
89 | self._reportProgress();
90 | });
91 | this._subreporters.push({ expectedDuration: expectedDuration, reporter: subreporter });
92 | return subreporter;
93 | },
94 | addSubreporters: function (expectedDurations) {
95 | var reporters = {};
96 | for (var key in expectedDurations) {
97 | reporters[key] = this.addSubreporter(expectedDurations[key]);
98 | }
99 | return reporters;
100 | },
101 | begin: function (action) {
102 | this._startTime = Date.now();
103 | this._state = ProgressReporter.STATE_DOING;
104 | this._action = action;
105 | this._reportProgress();
106 | },
107 | setProgress: function (progress) {
108 | if (this._subreporters.length > 0)
109 | throw "Can't call setProgress on a progress reporter with subreporters";
110 | if (progress != this._progress &&
111 | (progress == 1 ||
112 | (isNaN(progress) != isNaN(this._progress)) ||
113 | (progress - this._progress >= 0.01))) {
114 | this._progress = progress;
115 | if (progress == 1)
116 | this._transitionToFinished();
117 | this._reportProgress();
118 | }
119 | },
120 | finish: function () {
121 | this.setProgress(1);
122 | },
123 | _recalculateProgressFromSubreporters: function () {
124 | if (this._subreporters.length == 0)
125 | throw "Can't _recalculateProgressFromSubreporters on a progress reporter without any subreporters";
126 | this._progress = 0;
127 | for (var i = 0; i < this._subreporters.length; i++) {
128 | var expectedDuration = this._subreporters[i].expectedDuration;
129 | var reporter = this._subreporters[i].reporter;
130 | this._progress += reporter.getProgress() * expectedDuration / this._subreporterExpectedDurationsSum;
131 | }
132 | },
133 | _recalculateStateAndActionFromSubreporters: function () {
134 | if (this._subreporters.length == 0)
135 | throw "Can't _recalculateStateAndActionFromSubreporters on a progress reporter without any subreporters";
136 | var actions = [];
137 | var allWaiting = true;
138 | var allFinished = true;
139 | for (var i = 0; i < this._subreporters.length; i++) {
140 | var expectedDuration = this._subreporters[i].expectedDuration;
141 | var reporter = this._subreporters[i].reporter;
142 | var state = reporter.getState();
143 | if (state != ProgressReporter.STATE_WAITING)
144 | allWaiting = false;
145 | if (state != ProgressReporter.STATE_FINISHED)
146 | allFinished = false;
147 | if (state == ProgressReporter.STATE_DOING)
148 | actions.push(reporter.getAction());
149 | }
150 | if (allFinished) {
151 | this._transitionToFinished();
152 | } else if (!allWaiting) {
153 | this._state = ProgressReporter.STATE_DOING;
154 | if (actions.length == 0) {
155 | this._action = "About to start next task..."
156 | } else {
157 | this._action = actions.join("\n");
158 | }
159 | }
160 | },
161 | _transitionToFinished: function () {
162 | this._state = ProgressReporter.STATE_FINISHED;
163 |
164 | if (gDebugExpectedDurations) {
165 | this._realDuration = Date.now() - this._startTime;
166 | if (this._subreporters.length) {
167 | for (var i = 0; i < this._subreporters.length; i++) {
168 | var expectedDuration = this._subreporters[i].expectedDuration;
169 | var reporter = this._subreporters[i].reporter;
170 | var realDuration = reporter._realDuration;
171 | dump("For reporter with expectedDuration " + expectedDuration + ", real duration was " + realDuration + "\n");
172 | }
173 | }
174 | }
175 | },
176 | _reportProgress: function () {
177 | for (var i = 0; i < this._observers.length; i++) {
178 | this._observers[i](this);
179 | }
180 | },
181 | };
182 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/alignpat.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | function AlignmentPattern(posX, posY, estimatedModuleSize)
27 | {
28 | this.x=posX;
29 | this.y=posY;
30 | this.count = 1;
31 | this.estimatedModuleSize = estimatedModuleSize;
32 |
33 | this.__defineGetter__("EstimatedModuleSize", function()
34 | {
35 | return this.estimatedModuleSize;
36 | });
37 | this.__defineGetter__("Count", function()
38 | {
39 | return this.count;
40 | });
41 | this.__defineGetter__("X", function()
42 | {
43 | return Math.floor(this.x);
44 | });
45 | this.__defineGetter__("Y", function()
46 | {
47 | return Math.floor(this.y);
48 | });
49 | this.incrementCount = function()
50 | {
51 | this.count++;
52 | }
53 | this.aboutEquals=function( moduleSize, i, j)
54 | {
55 | if (Math.abs(i - this.y) <= moduleSize && Math.abs(j - this.x) <= moduleSize)
56 | {
57 | var moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);
58 | return moduleSizeDiff <= 1.0 || moduleSizeDiff / this.estimatedModuleSize <= 1.0;
59 | }
60 | return false;
61 | }
62 |
63 | }
64 |
65 | function AlignmentPatternFinder( image, startX, startY, width, height, moduleSize, resultPointCallback)
66 | {
67 | this.image = image;
68 | this.possibleCenters = new Array();
69 | this.startX = startX;
70 | this.startY = startY;
71 | this.width = width;
72 | this.height = height;
73 | this.moduleSize = moduleSize;
74 | this.crossCheckStateCount = new Array(0,0,0);
75 | this.resultPointCallback = resultPointCallback;
76 |
77 | this.centerFromEnd=function(stateCount, end)
78 | {
79 | return (end - stateCount[2]) - stateCount[1] / 2.0;
80 | }
81 | this.foundPatternCross = function(stateCount)
82 | {
83 | var moduleSize = this.moduleSize;
84 | var maxVariance = moduleSize / 2.0;
85 | for (var i = 0; i < 3; i++)
86 | {
87 | if (Math.abs(moduleSize - stateCount[i]) >= maxVariance)
88 | {
89 | return false;
90 | }
91 | }
92 | return true;
93 | }
94 |
95 | this.crossCheckVertical=function( startI, centerJ, maxCount, originalStateCountTotal)
96 | {
97 | var image = this.image;
98 |
99 | var maxI = qrcode.height;
100 | var stateCount = this.crossCheckStateCount;
101 | stateCount[0] = 0;
102 | stateCount[1] = 0;
103 | stateCount[2] = 0;
104 |
105 | // Start counting up from center
106 | var i = startI;
107 | while (i >= 0 && image[centerJ + i*qrcode.width] && stateCount[1] <= maxCount)
108 | {
109 | stateCount[1]++;
110 | i--;
111 | }
112 | // If already too many modules in this state or ran off the edge:
113 | if (i < 0 || stateCount[1] > maxCount)
114 | {
115 | return NaN;
116 | }
117 | while (i >= 0 && !image[centerJ + i*qrcode.width] && stateCount[0] <= maxCount)
118 | {
119 | stateCount[0]++;
120 | i--;
121 | }
122 | if (stateCount[0] > maxCount)
123 | {
124 | return NaN;
125 | }
126 |
127 | // Now also count down from center
128 | i = startI + 1;
129 | while (i < maxI && image[centerJ + i*qrcode.width] && stateCount[1] <= maxCount)
130 | {
131 | stateCount[1]++;
132 | i++;
133 | }
134 | if (i == maxI || stateCount[1] > maxCount)
135 | {
136 | return NaN;
137 | }
138 | while (i < maxI && !image[centerJ + i*qrcode.width] && stateCount[2] <= maxCount)
139 | {
140 | stateCount[2]++;
141 | i++;
142 | }
143 | if (stateCount[2] > maxCount)
144 | {
145 | return NaN;
146 | }
147 |
148 | var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
149 | if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal)
150 | {
151 | return NaN;
152 | }
153 |
154 | return this.foundPatternCross(stateCount)?this.centerFromEnd(stateCount, i):NaN;
155 | }
156 |
157 | this.handlePossibleCenter=function( stateCount, i, j)
158 | {
159 | var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
160 | var centerJ = this.centerFromEnd(stateCount, j);
161 | var centerI = this.crossCheckVertical(i, Math.floor (centerJ), 2 * stateCount[1], stateCountTotal);
162 | if (!isNaN(centerI))
163 | {
164 | var estimatedModuleSize = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0;
165 | var max = this.possibleCenters.length;
166 | for (var index = 0; index < max; index++)
167 | {
168 | var center = this.possibleCenters[index];
169 | // Look for about the same center and module size:
170 | if (center.aboutEquals(estimatedModuleSize, centerI, centerJ))
171 | {
172 | return new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
173 | }
174 | }
175 | // Hadn't found this before; save it
176 | var point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
177 | this.possibleCenters.push(point);
178 | if (this.resultPointCallback != null)
179 | {
180 | this.resultPointCallback.foundPossibleResultPoint(point);
181 | }
182 | }
183 | return null;
184 | }
185 |
186 | this.find = function()
187 | {
188 | var startX = this.startX;
189 | var height = this.height;
190 | var maxJ = startX + width;
191 | var middleI = startY + (height >> 1);
192 | // We are looking for black/white/black modules in 1:1:1 ratio;
193 | // this tracks the number of black/white/black modules seen so far
194 | var stateCount = new Array(0,0,0);
195 | for (var iGen = 0; iGen < height; iGen++)
196 | {
197 | // Search from middle outwards
198 | var i = middleI + ((iGen & 0x01) == 0?((iGen + 1) >> 1):- ((iGen + 1) >> 1));
199 | stateCount[0] = 0;
200 | stateCount[1] = 0;
201 | stateCount[2] = 0;
202 | var j = startX;
203 | // Burn off leading white pixels before anything else; if we start in the middle of
204 | // a white run, it doesn't make sense to count its length, since we don't know if the
205 | // white run continued to the left of the start point
206 | while (j < maxJ && !image[j + qrcode.width* i])
207 | {
208 | j++;
209 | }
210 | var currentState = 0;
211 | while (j < maxJ)
212 | {
213 | if (image[j + i*qrcode.width])
214 | {
215 | // Black pixel
216 | if (currentState == 1)
217 | {
218 | // Counting black pixels
219 | stateCount[currentState]++;
220 | }
221 | else
222 | {
223 | // Counting white pixels
224 | if (currentState == 2)
225 | {
226 | // A winner?
227 | if (this.foundPatternCross(stateCount))
228 | {
229 | // Yes
230 | var confirmed = this.handlePossibleCenter(stateCount, i, j);
231 | if (confirmed != null)
232 | {
233 | return confirmed;
234 | }
235 | }
236 | stateCount[0] = stateCount[2];
237 | stateCount[1] = 1;
238 | stateCount[2] = 0;
239 | currentState = 1;
240 | }
241 | else
242 | {
243 | stateCount[++currentState]++;
244 | }
245 | }
246 | }
247 | else
248 | {
249 | // White pixel
250 | if (currentState == 1)
251 | {
252 | // Counting black pixels
253 | currentState++;
254 | }
255 | stateCount[currentState]++;
256 | }
257 | j++;
258 | }
259 | if (this.foundPatternCross(stateCount))
260 | {
261 | var confirmed = this.handlePossibleCenter(stateCount, i, maxJ);
262 | if (confirmed != null)
263 | {
264 | return confirmed;
265 | }
266 | }
267 | }
268 |
269 | // Hmm, nothing we saw was observed and confirmed twice. If we had
270 | // any guess at all, return it.
271 | if (!(this.possibleCenters.length == 0))
272 | {
273 | return this.possibleCenters[0];
274 | }
275 |
276 | throw "Couldn't find enough alignment patterns";
277 | }
278 |
279 | }
--------------------------------------------------------------------------------
/js/localStorage.js:
--------------------------------------------------------------------------------
1 | var PROFILE_EXPIRE_TIME = 7 * 24 * 60 * 60 * 1000;
2 |
3 | // Simple wrapper for an abstract local storage provider (indexedDB)
4 | // to provide a key based JSON storage.
5 | function JSONStorage() {
6 | this._indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
7 | this._db = null;
8 | this._pendingRequests = [];
9 | if (!this._indexedDB)
10 | return; // No storage
11 |
12 | var dbRequest = this._indexedDB.open("cleopatra", 2);
13 | var self = this;
14 | dbRequest.onupgradeneeded = function(event) {
15 | PROFILERLOG("Upgrade cleopatra DB");
16 | var db = event.target.result;
17 | var store = db.createObjectStore("profiles", {keyPath: "storage_key"});
18 | }
19 | dbRequest.onsuccess = function(event) {
20 | PROFILERLOG("'cleopatra' database open");
21 | self._db = dbRequest.result;
22 | for (var i = 0; i < self._pendingRequests.length; i++) {
23 | self._pendingRequests[i]();
24 | }
25 | self._pendingRequests = [];
26 | };
27 |
28 | }
29 | JSONStorage.prototype = {
30 | setValue: function JSONStorage_setValue(key, value, callback) {
31 | if (!this._db) {
32 | var self = this;
33 | this._pendingRequests.push(function pendingSetValue() {
34 | self.setValue(key, value, callback);
35 | });
36 | return;
37 | }
38 | try {
39 | this._db.transaction("profiles", "readwrite").objectStore("profiles").put( {storage_key: key, value: value} );
40 | } catch (e) {
41 | dump("localStorage error: " + e + "\n");
42 | return;
43 | }
44 | //PROFILERTRACE("JSONStorage['" + key + "'] set " + JSON.stringify(value));
45 | if (callback)
46 | callback();
47 | },
48 |
49 | getValue: function JSONStorage_getValue(key, callback) {
50 | if (!this._db) {
51 | var self = this;
52 | this._pendingRequests.push(function pendingGetValue() {
53 | self.getValue(key, callback);
54 | });
55 | return;
56 | }
57 | var transaction = this._db.transaction("profiles");
58 | var request = transaction.objectStore("profiles").get(key);
59 | request.onsuccess = function(event) {
60 | if (!callback)
61 | return;
62 | //PROFILERTRACE("JSONStorage['" + key + "'] get " + JSON.stringify(request.result));
63 | if (request.result) {
64 | callback(request.result.value);
65 | } else {
66 | callback(null);
67 | }
68 | }
69 | request.onerror = function() {
70 | PROFILERERROR("Error getting value from indexedDB");
71 | }
72 | },
73 |
74 | deleteValue: function JSONStorage_deleteValue(key, callback) {
75 | if (!this._db) {
76 | var self = this;
77 | this._pendingRequests.push(function pendingDeleteValue() {
78 | self.deleteValue(key, callback);
79 | });
80 | return;
81 | }
82 | var transaction = this._db.transaction("profiles", "readwrite");
83 | var request = transaction.objectStore("profiles").delete(key);
84 | request.onsuccess = function(event) {
85 | if (!callback)
86 | return;
87 | //PROFILERTRACE("JSONStorage['" + key + "'] get " + JSON.stringify(request.result));
88 | if (request.result) {
89 | callback(request.result.value);
90 | } else {
91 | callback(null);
92 | }
93 | }
94 | request.onerror = function() {
95 | PROFILERERROR("Error deleting value from indexedDB");
96 | }
97 | },
98 |
99 | clearStorage: function JSONStorage_clearStorage(callback) {
100 | if (!this._db) {
101 | var self = this;
102 | this._pendingRequests.push(function pendingSetValue() {
103 | self.clearStorage(callback);
104 | });
105 | return;
106 | }
107 | var transaction = this._db.transaction("profiles", "readwrite");
108 | var request = transaction.objectStore("profiles").clear();
109 | request.onsuccess = function() {
110 | PROFILERLOG("Cleared local profile storage");
111 | if (callback)
112 | callback();
113 | }
114 | },
115 | }
116 |
117 | function ProfileLocalStorage() {
118 | this._storage = new JSONStorage();
119 | this._profileListChangeCallback = null;
120 | }
121 | ProfileLocalStorage.prototype = {
122 | onProfileListChange: function ProfileLocalStorage_OnProfileListChange(callback) {
123 | this._profileListChangeCallback = callback;
124 | },
125 |
126 | getProfileList: function ProfileLocalStorage_getProfileList(callback) {
127 | this._storage.getValue("profileList", function gotProfileList(profileList) {
128 | profileList = profileList || [];
129 | callback(profileList);
130 | });
131 | },
132 |
133 | storeLocalProfile: function ProfileLocalStorage_storeLocalProfile(profile, profileKey, callback, custom_info) {
134 | var self = this;
135 | custom_info = custom_info || {};
136 | var date = new Date();
137 | var time = date.getTime();
138 | var name = custom_info.name || "Local Profile";
139 | if (name == "profileList") {
140 | // Make sure we don't override our profile list entry
141 | name = "Profile List";
142 | }
143 | this.getProfileList(function got_profile(profileList) {
144 | profileKey = profileKey || "local_profile:" + time;
145 | for (var i = 0; i < profileList.length; i++) {
146 | if (profileList[i].profileKey == profileKey) {
147 | return;
148 | }
149 | }
150 | var tempProfileCount = 0;
151 | for (profileIndex in profileList) {
152 | var currProfile = profileList[profileIndex];
153 | if (currProfile.retain == false) {
154 | tempProfileCount++;
155 | }
156 | }
157 | var profilesToRemove = tempProfileCount - 5;
158 | for (profileIndex in profileList) {
159 | var currProfile = profileList[profileIndex];
160 | if (currProfile.retain == false && profilesToRemove > 0) {
161 | self._deleteLocalProfile(profileToRemove);
162 | }
163 | }
164 | if (profileList.length >= 5) {
165 | var profileToRemove = profileList[0].profileKey;
166 | self._deleteLocalProfile(profileToRemove);
167 | profileList.shift();
168 | }
169 | profileList.push( {profileKey: profileKey, key: profileKey, name: name, date: date.getTime(), expire: time + PROFILE_EXPIRE_TIME, storedTime: time} );
170 | self._storage.setValue(profileKey, profile, function complete() {
171 | self._storage.setValue("profileList", profileList);
172 | if (callback)
173 | callback(profileKey);
174 | if (self._profileListChangeCallback) {
175 | self._profileListChangeCallback(profileList);
176 | }
177 | });
178 | });
179 | },
180 |
181 | renameProfile: function ProfileLocalStorage_renameProfile(profileKey, name) {
182 | var self = this;
183 | if (name == "profileList") {
184 | // Make sure we don't override our profile list entry
185 | name = "Profile List";
186 | }
187 | this.getProfileList(function renameProfileWithList(profileList) {
188 | for (var profileIndex in profileList) {
189 | var profileInfo = profileList[profileIndex];
190 | if (profileInfo.profileKey == profileKey) {
191 | profileInfo.name = name;
192 | profileInfo.retain = true;
193 | self._storage.setValue("profileList", profileList);
194 | return;
195 | }
196 | }
197 | });
198 | },
199 |
200 | getProfile: function ProfileLocalStorage_getProfile(profileKey, callback) {
201 | this._storage.getValue(profileKey, function(profile) {
202 | callback(profile);
203 | });
204 | },
205 |
206 | // This version doesn't update the profileList entry
207 | _deleteLocalProfile: function ProfileLocalStorage__deleteLocalProfile(profileKey, callback) {
208 | this._storage.deleteValue(profileKey, callback);
209 | },
210 |
211 | deleteLocalProfile: function ProfileLocalStorage_deleteLocalProfile(profileKey, callback) {
212 | var self = this;
213 | this._storage.deleteValue(profileKey, function () {
214 | self.getProfileList(function got_profile(profileList) {
215 | for (var profileIndex in profileList) {
216 | var profileInfo = profileList[profileIndex];
217 | if (profileInfo.profileKey == profileKey) {
218 | profileList.splice(profileIndex, 1);
219 | self._storage.setValue("profileList", profileList, callback);
220 | break;
221 | }
222 | }
223 | });
224 | });
225 | },
226 |
227 | clearStorage: function ProfileLocalStorage_clearStorage(callback) {
228 | this._storage.clearStorage(callback);
229 | },
230 | };
231 |
232 | var gLocalStorage = new ProfileLocalStorage();
233 |
234 | function quickTest() {
235 | gLocalStorage.getProfileList(function(profileList) {
236 | gLocalStorage.storeLocalProfile({}, function() {
237 | gLocalStorage.clearStorage();
238 | });
239 | });
240 | }
241 |
242 | function receiveMessage(event) {
243 | if (event.data.spsProfile) {
244 | var spsProfileStr = event.data.spsProfile;
245 | gLocalStorage.storeLocalProfile(spsProfileStr, null, function profileSaved(key) {
246 | var msg = {
247 | "type": "spsProfileReceived",
248 | "key": key,
249 | };
250 |
251 | event.source.postMessage(msg, "*");
252 | });
253 | }
254 | }
255 |
256 | window.addEventListener("message", receiveMessage, false);
257 |
258 | //quickTest();
259 |
--------------------------------------------------------------------------------
/js/markerTree.js:
--------------------------------------------------------------------------------
1 |
2 | function MarkerTreeManager() {
3 | this.treeView = new TreeView();
4 | this.treeView.setColumns([
5 | { name: "markerType", title: "Type" },
6 | { name: "markerCount", title: "Time" },
7 | { name: "resource", title: "" },
8 | { name: "markerName", title: "Marker Name"}
9 | ]);
10 | this.treeView._HTMLForFunction = this._HTMLForFunction;
11 | var self = this;
12 | this.treeView.addEventListener("select", function (frameData) {
13 | //self.highlightFrame(frameData);
14 | //if (window.comparator_setSelection) {
15 | // window.comparator_setSelection(gTreeManager.serializeCurrentSelectionSnapshot(), frameData);
16 | //}
17 | });
18 | this.treeView.addEventListener("select", function (markerData) {
19 | function selectMarkerDiv(markerDiv) {
20 | if (self.lastSelected) {
21 | self.lastSelected.style.fontWeight = "normal";
22 | self.lastSelected.style.zIndex = "0";
23 | self.lastSelected.style.maxWidth = "50px";
24 | }
25 | markerDiv.style.fontWeight = "bold";
26 | markerDiv.style.zIndex = "1";
27 | markerDiv.style.maxWidth = "300px";
28 | self.lastSelected = markerDiv;
29 | }
30 | var markerDivs = document.getElementsByClassName("marker");
31 | for (var i = 0; i < markerDivs.length; i++) {
32 | var markerDiv = markerDivs.item(i);
33 | var markers = markerDiv.markers;
34 | for (var j = 0; j < markers.length; j++) {
35 | var marker = markers[j];
36 | if (MarkerTreeManager.prototype.markerName(marker) == markerData.name && marker.time == markerData.time) {
37 | selectMarkerDiv(markerDiv);
38 | return;
39 | }
40 | }
41 | }
42 | });
43 | this._container = document.createElement("div");
44 | this._container.className = "tree";
45 | this._container.appendChild(this.treeView.getContainer());
46 | }
47 | MarkerTreeManager.prototype = {
48 | getContainer: function MarkerTreeManager_getContainer() {
49 | return this._container;
50 | },
51 | highlightFrame: function Treedisplay_highlightFrame(frameData) {
52 | /**
53 | * @todo Decouple AppUI
54 | */
55 | AppUI.setHighlightedCallstack(this._getCallstackUpTo(frameData), this._getHeaviestCallstack(frameData));
56 | },
57 | dataIsOutdated: function MarkerTreeManager_dataIsOutdated() {
58 | this.treeView.dataIsOutdated();
59 | },
60 | setSelection: function MarkerTreeManager_setSelection(frames) {
61 | return this.treeView.setSelection(frames);
62 | },
63 | display: function MarkerTreeManager_display(markers) {
64 | this.treeView.display(this.convertToJSTreeData(markers));
65 | },
66 | hide: function MarkerTreeManager_hide() {
67 | this._container.classList.add("hidden");
68 | },
69 | show: function MarkerTreeManager_show() {
70 | this._container.classList.remove("hidden");
71 | },
72 | getTreeHeader: function MarkerTreeManager_getTreeHeader() {
73 | return this.treeView.getTreeHeader();
74 | },
75 | selectMarker: function MarkerTreeManager_selectMarker(marker) {
76 | this.treeView.setSelection(["(markers)", this.markerName(marker)]);
77 | },
78 | _HTMLForFunction: function MarkerTreeManager__HTMLForFunction(node, depth) {
79 | //TODO: fix xss
80 | return '' +
81 | 'Marker ' +
82 | ' ' +
83 | '' + Math.round(node.time) + ' ' +
84 | ' ' +
85 | '' +
86 | '' + node.name + '' +
87 | '' + node.library + '' +
88 | '';
89 | },
90 | markerName: function markerName(marker){
91 | if (marker.marker &&
92 | marker.marker.data &&
93 | marker.marker.data.filename) {
94 | return marker.name + ': ' + marker.marker.data.filename;
95 | }
96 | else {
97 | return marker.name;
98 | }
99 | },
100 | buildTreeForStack: function MarkerTreeManager_buildTreeForStack(stack, pos) {
101 | var self = this;
102 | return [{getData: function() { return self._buildTreeForStackInternal(stack, pos); }}];
103 | },
104 | _buildTreeForStackInternal: function MarkerTreeManager_buildTreeForStackInternal(stack, pos) {
105 | pos = pos | 0;
106 | if (pos >= stack.length) {
107 | return null;
108 | }
109 | var self = this;
110 | var rootObj = {};
111 | rootObj.counter = 0;
112 | rootObj.time = "";
113 | rootObj.name = stack[pos];
114 | rootObj.library = "";
115 | if (pos+1 < stack.length) {
116 | rootObj.children = [{getData: function() { return self._buildTreeForStackInternal(stack, pos+1); }}];
117 | }
118 | return rootObj;
119 | },
120 | convertToJSTreeData: function MarkerTreeManager__convertToJSTreeData(markers) {
121 | var self = this;
122 | function createMarkerTreeViewNode(marker, parent) {
123 | var currObj = {};
124 | currObj.parent = parent;
125 | currObj.counter = 0;
126 | currObj.time = marker.time;
127 | currObj.name = MarkerTreeManager.prototype.markerName(marker);
128 | //if (marker.marker.data && marker.marker.data.interval) {
129 | // currObj.name += marker.marker.data.interval;
130 | //}
131 | currObj.library = "Main Thread";
132 | currObj.marker = marker;
133 | if (marker.marker.data && marker.marker.data.type == "innerHTML") {
134 | currObj.children = [ {
135 | getData: function() {
136 | var child = {};
137 | child.parent = currObj;
138 | child.counter = 0;
139 | child.time = marker.time;
140 | child.name = marker.marker.data.innerHTML;
141 | child.library = "";
142 | child.marker = marker;
143 | return child;
144 | }
145 | }];
146 | } else if (marker.marker.data && marker.marker.data.stack) {
147 | currObj.children = self.buildTreeForStack(marker.marker.data.stack);
148 | /*
149 | [ {
150 | getData: function() {
151 | var child = {};
152 | child.parent = currObj;
153 | child.counter = 0;
154 | child.time = marker.time;
155 | child.name = "stack";
156 | child.library = "";
157 | child.marker = marker;
158 | return child;
159 | }
160 | }];
161 | */
162 | }
163 | return currObj;
164 | }
165 | function getMarkerChildrenObjects(markers, parent) {
166 | var markers = markers.slice(0);
167 | return markers.map(function (child) {
168 | var createdNode = null;
169 | return {
170 | getData: function () {
171 | if (!createdNode) {
172 | createdNode = createMarkerTreeViewNode(child, parent);
173 | }
174 | return createdNode;
175 | }
176 | };
177 | });
178 | }
179 | var rootObj = {};
180 | rootObj.counter = 0;
181 | rootObj.time = "";
182 | rootObj.name = "(markers)";
183 | rootObj.library = "";
184 | rootObj.children = getMarkerChildrenObjects(markers, rootObj);
185 | return [{getData: function() { return rootObj; }}];
186 | var totalSamples = rootNode.counter;
187 | function createTreeViewNode(node, parent) {
188 | var curObj = {};
189 | curObj.parent = parent;
190 | curObj.counter = node.counter;
191 | var selfCounter = node.counter;
192 | for (var i = 0; i < node.children.length; ++i) {
193 | selfCounter -= node.children[i].counter;
194 | }
195 | curObj.selfCounter = selfCounter;
196 | curObj.ratio = node.counter / totalSamples;
197 | curObj.fullFrameNamesAsInSample = node.mergedNames ? node.mergedNames : [node.name];
198 | if (!(node.name in (useFunctions ? functions : symbols))) {
199 | curObj.name = node.name;
200 | curObj.library = "";
201 | } else {
202 | var functionObj = useFunctions ? functions[node.name] : functions[symbols[node.name].functionIndex];
203 | var info = {
204 | functionName: functionObj.functionName,
205 | libraryName: functionObj.libraryName,
206 | lineInformation: useFunctions ? "" : symbols[node.name].lineInformation
207 | };
208 | curObj.name = (info.functionName + " " + info.lineInformation).trim();
209 | curObj.library = info.libraryName;
210 | curObj.isJSFrame = functionObj.isJSFrame;
211 | if (functionObj.scriptLocation) {
212 | curObj.scriptLocation = functionObj.scriptLocation;
213 | }
214 | }
215 | if (node.children.length) {
216 | curObj.children = getChildrenObjects(node.children, curObj);
217 | }
218 | return curObj;
219 | }
220 | function getChildrenObjects(children, parent) {
221 | var sortedChildren = children.slice(0).sort(treeObjSort);
222 | return sortedChildren.map(function (child) {
223 | var createdNode = null;
224 | return {
225 | getData: function () {
226 | if (!createdNode) {
227 | createdNode = createTreeViewNode(child, parent);
228 | }
229 | return createdNode;
230 | }
231 | };
232 | });
233 | }
234 | return getChildrenObjects([rootNode], null);
235 | },
236 | };
237 |
238 |
239 |
--------------------------------------------------------------------------------
/js/profileTreeManager.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function(window) {
4 | function treeObjSort(a, b) {
5 | return b.counter - a.counter;
6 | }
7 |
8 | function ProfileTreeManager() {
9 | this.treeView = new TreeView();
10 | this.treeView.setColumns([
11 | { name: "sampleCount", title: "Running time" },
12 | { name: "selfSampleCount", title: "Self" },
13 | { name: "resource", title: "" },
14 | { name: "symbolName", title: "Symbol Name"}
15 | ]);
16 | AppUI.MakeSizeAdjustable(this.treeView.getTreeHeader(), gHistogramContainer.container.parentNode);
17 | var self = this;
18 | this.treeView.addEventListener("select", function (frameData) {
19 | self.highlightFrame(frameData);
20 | if (window.comparator_setSelection) {
21 | window.comparator_setSelection(gTreeManager.serializeCurrentSelectionSnapshot(), frameData);
22 | }
23 | });
24 | this.treeView.addEventListener("contextMenuClick", function (e) {
25 | self._onContextMenuClick(e);
26 | });
27 | this.treeView.addEventListener("focusCallstackButtonClicked", function (frameData) {
28 | var focusedCallstack = self._getCallstackUpTo(frameData);
29 | /**
30 | * @todo Decouple AppUI
31 | */
32 | AppUI.focusOnCallstack(focusedCallstack, frameData.name);
33 | });
34 | this._container = document.createElement("div");
35 | this._container.className = "tree";
36 | this._container.appendChild(this.treeView.getContainer());
37 |
38 | // If this is set when the tree changes the snapshot is immediately restored.
39 | this._savedSnapshot = null;
40 | }
41 | ProfileTreeManager.prototype = {
42 | getContainer: function ProfileTreeManager_getContainer() {
43 | return this._container;
44 | },
45 | highlightFrame: function Treedisplay_highlightFrame(frameData) {
46 | /**
47 | * @todo Decouple AppUI
48 | */
49 | AppUI.setHighlightedCallstack(this._getCallstackUpTo(frameData), this._getHeaviestCallstack(frameData));
50 | },
51 | dataIsOutdated: function ProfileTreeManager_dataIsOutdated() {
52 | this.treeView.dataIsOutdated();
53 | },
54 | saveSelectionSnapshot: function ProfileTreeManager_saveSelectionSnapshot(isJavascriptOnly) {
55 | this._savedSnapshot = this.treeView.getSelectionSnapshot(isJavascriptOnly);
56 | },
57 | saveReverseSelectionSnapshot: function ProfileTreeManager_saveReverseSelectionSnapshot(isJavascriptOnly) {
58 | this._savedSnapshot = this.treeView.getReverseSelectionSnapshot(isJavascriptOnly);
59 | },
60 | hasNonTrivialSelection: function ProfileTreeManager_hasNonTrivialSelection() {
61 | return this.treeView.getSelectionSnapshot().length > 1;
62 | },
63 | serializeCurrentSelectionSnapshot: function ProfileTreeManager_serializeCurrentSelectionSnapshot() {
64 | var str = JSON.stringify(this.treeView.getSelectionSnapshot());
65 | console.log(str);
66 | return str.substring(1, str.length - 1);
67 | },
68 | restoreSerializedSelectionSnapshot: function ProfileTreeManager_restoreSerializedSelectionSnapshot(selection) {
69 | this._savedSnapshot = JSON.parse("[" + selection + "]");
70 | },
71 | _restoreSelectionSnapshot: function ProfileTreeManager__restoreSelectionSnapshot(snapshot, allowNonContigous) {
72 | return this.treeView.restoreSelectionSnapshot(snapshot, allowNonContigous);
73 | },
74 | setSelection: function ProfileTreeManager_setSelection(frames, inverted) {
75 | return this.treeView.setSelection(frames, inverted);
76 | },
77 | _getCallstackUpTo: function ProfileTreeManager__getCallstackUpTo(frame) {
78 | var callstack = [];
79 | var curr = frame;
80 | while (curr != null) {
81 | if (curr.name != null) {
82 | var subCallstack = curr.fullFrameNamesAsInSample.clone();
83 | subCallstack.reverse();
84 | callstack = callstack.concat(subCallstack);
85 | }
86 | curr = curr.parent;
87 | }
88 | callstack.reverse();
89 | if (gInvertCallstack)
90 | callstack.shift(); // remove (total)
91 | return callstack;
92 | },
93 | _getHeaviestCallstack: function ProfileTreeManager__getHeaviestCallstack(frame) {
94 | // FIXME: This gets the first leaf which is not the heaviest leaf.
95 | while(frame.children && frame.children.length > 0) {
96 | var nextFrame = frame.children[0].getData();
97 | if (!nextFrame)
98 | break;
99 | frame = nextFrame;
100 | }
101 | return this._getCallstackUpTo(frame);
102 | },
103 | _onContextMenuClick: function ProfileTreeManager__onContextMenuClick(e) {
104 | var node = e.node;
105 | var menuItem = e.menuItem;
106 |
107 | if (menuItem == "View Source") {
108 | // Remove anything after ( since MXR doesn't handle search with the arguments.
109 | var symbol = node.name.split("(")[0];
110 | window.open("http://mxr.mozilla.org/mozilla-central/search?string=" + symbol, "View Source");
111 | } else if (menuItem == "View JS Source") {
112 | this.viewJSSource(node);
113 | } else if (menuItem == "Plugin View: Pie") {
114 | focusOnPluginView("protovis", {type:"pie"});
115 | } else if (menuItem == "Plugin View: Tree") {
116 | focusOnPluginView("protovis", {type:"tree"});
117 | } else if (menuItem == "Google Search") {
118 | var symbol = node.name;
119 | window.open("https://www.google.ca/search?q=" + symbol, "View Source");
120 | } else if (menuItem == "Focus Frame") {
121 | var symbol = node.fullFrameNamesAsInSample[0]; // TODO: we only function one symbol when callpath merging is on, fix that
122 | /**
123 | * @todo Decouple AppUI
124 | */
125 | AppUI.focusOnSymbol(symbol, node.name);
126 | } else if (menuItem == "Focus Callstack") {
127 | var focusedCallstack = this._getCallstackUpTo(node);
128 | /**
129 | * @todo Decouple AppUI
130 | */
131 | AppUI.focusOnCallstack(focusedCallstack, node.name);
132 | }
133 | },
134 | setAllowNonContigous: function ProfileTreeManager_setAllowNonContigous() {
135 | this._allowNonContigous = true;
136 | },
137 | display: function ProfileTreeManager_display(tree, symbols, functions, resources, useFunctions, filterByName) {
138 | this.treeView.display(this.convertToJSTreeData(tree, symbols, functions, useFunctions), resources, filterByName);
139 | if (this._savedSnapshot) {
140 | var old = this._savedSnapshot.clone();
141 | this._restoreSelectionSnapshot(this._savedSnapshot, this._allowNonContigous);
142 | this._savedSnapshot = old;
143 | this._allowNonContigous = false;
144 | }
145 | },
146 | convertToJSTreeData: function ProfileTreeManager__convertToJSTreeData(rootNode, symbols, functions, useFunctions) {
147 | var totalSamples = rootNode.counter;
148 | function createTreeViewNode(node, parent) {
149 | var curObj = {};
150 | curObj.parent = parent;
151 | curObj.counter = node.counter;
152 | var selfCounter = node.counter;
153 | for (var i = 0; i < node.children.length; ++i) {
154 | selfCounter -= node.children[i].counter;
155 | }
156 | curObj.selfCounter = selfCounter;
157 | curObj.ratio = node.counter / totalSamples;
158 | curObj.fullFrameNamesAsInSample = node.mergedNames ? node.mergedNames : [node.name];
159 | if (!(node.name in (useFunctions ? functions : symbols))) {
160 | curObj.name = node.name;
161 | curObj.library = "";
162 | } else {
163 | var functionObj = useFunctions ? functions[node.name] : functions[symbols[node.name].functionIndex];
164 | var info = {
165 | functionName: functionObj.functionName,
166 | libraryName: functionObj.libraryName,
167 | lineInformation: useFunctions ? "" : symbols[node.name].lineInformation
168 | };
169 | curObj.name = (info.functionName + " " + info.lineInformation).trim();
170 | curObj.library = info.libraryName;
171 | curObj.isJSFrame = functionObj.isJSFrame;
172 | if (functionObj.scriptLocation) {
173 | curObj.scriptLocation = functionObj.scriptLocation;
174 | }
175 | }
176 | if (node.children.length) {
177 | curObj.children = getChildrenObjects(node.children, curObj);
178 | }
179 | return curObj;
180 | }
181 | function getChildrenObjects(children, parent) {
182 | var sortedChildren = children.slice(0).sort(treeObjSort);
183 | return sortedChildren.map(function (child) {
184 | var createdNode = null;
185 | return {
186 | getData: function () {
187 | if (!createdNode) {
188 | createdNode = createTreeViewNode(child, parent);
189 | }
190 | return createdNode;
191 | }
192 | };
193 | });
194 | }
195 | return getChildrenObjects([rootNode], null);
196 | },
197 | viewJSSource: function ProfileTreeManager_viewJSSource(sample) {
198 | var sourceView = new SourceView();
199 | sourceView.setScriptLocation(sample.scriptLocation);
200 | sourceView.setSource(gMeta.js.source[sample.scriptLocation.scriptURI]);
201 | gMainArea.appendChild(sourceView.getContainer());
202 | },
203 | focusOnPluginView: function ProfileTreeManager_focusOnPluginView(pluginName, param) {
204 | var filter = {
205 | type: "PluginView",
206 | pluginName: pluginName,
207 | param: param,
208 | };
209 | var newFilterChain = gSampleFilters.concat([filter]);
210 | gBreadcrumbTrail.addAndEnter({
211 | title: "Plugin View: " + pluginName,
212 | enterCallback: function () {
213 | gSampleFilters = newFilterChain;
214 | window.dispatchEvent(new CustomEvent('filters-changed'));
215 | }
216 | })
217 | }
218 | };
219 | window.ProfileTreeManager = ProfileTreeManager;
220 | }(this));
221 |
--------------------------------------------------------------------------------
/js/qr/jsqrcode/databr.js:
--------------------------------------------------------------------------------
1 | /*
2 | Ported to JavaScript by Lazar Laszlo 2011
3 |
4 | lazarsoft@gmail.com, www.lazarsoft.info
5 |
6 | */
7 |
8 | /*
9 | *
10 | * Copyright 2007 ZXing authors
11 | *
12 | * Licensed under the Apache License, Version 2.0 (the "License");
13 | * you may not use this file except in compliance with the License.
14 | * You may obtain a copy of the License at
15 | *
16 | * http://www.apache.org/licenses/LICENSE-2.0
17 | *
18 | * Unless required by applicable law or agreed to in writing, software
19 | * distributed under the License is distributed on an "AS IS" BASIS,
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | * See the License for the specific language governing permissions and
22 | * limitations under the License.
23 | */
24 |
25 |
26 | function QRCodeDataBlockReader(blocks, version, numErrorCorrectionCode)
27 | {
28 | this.blockPointer = 0;
29 | this.bitPointer = 7;
30 | this.dataLength = 0;
31 | this.blocks = blocks;
32 | this.numErrorCorrectionCode = numErrorCorrectionCode;
33 | if (version <= 9)
34 | this.dataLengthMode = 0;
35 | else if (version >= 10 && version <= 26)
36 | this.dataLengthMode = 1;
37 | else if (version >= 27 && version <= 40)
38 | this.dataLengthMode = 2;
39 |
40 | this.getNextBits = function( numBits)
41 | {
42 | var bits = 0;
43 | if (numBits < this.bitPointer + 1)
44 | {
45 | // next word fits into current data block
46 | var mask = 0;
47 | for (var i = 0; i < numBits; i++)
48 | {
49 | mask += (1 << i);
50 | }
51 | mask <<= (this.bitPointer - numBits + 1);
52 |
53 | bits = (this.blocks[this.blockPointer] & mask) >> (this.bitPointer - numBits + 1);
54 | this.bitPointer -= numBits;
55 | return bits;
56 | }
57 | else if (numBits < this.bitPointer + 1 + 8)
58 | {
59 | // next word crosses 2 data blocks
60 | var mask1 = 0;
61 | for (var i = 0; i < this.bitPointer + 1; i++)
62 | {
63 | mask1 += (1 << i);
64 | }
65 | bits = (this.blocks[this.blockPointer] & mask1) << (numBits - (this.bitPointer + 1));
66 | this.blockPointer++;
67 | bits += ((this.blocks[this.blockPointer]) >> (8 - (numBits - (this.bitPointer + 1))));
68 |
69 | this.bitPointer = this.bitPointer - numBits % 8;
70 | if (this.bitPointer < 0)
71 | {
72 | this.bitPointer = 8 + this.bitPointer;
73 | }
74 | return bits;
75 | }
76 | else if (numBits < this.bitPointer + 1 + 16)
77 | {
78 | // next word crosses 3 data blocks
79 | var mask1 = 0; // mask of first block
80 | var mask3 = 0; // mask of 3rd block
81 | //bitPointer + 1 : number of bits of the 1st block
82 | //8 : number of the 2nd block (note that use already 8bits because next word uses 3 data blocks)
83 | //numBits - (bitPointer + 1 + 8) : number of bits of the 3rd block
84 | for (var i = 0; i < this.bitPointer + 1; i++)
85 | {
86 | mask1 += (1 << i);
87 | }
88 | var bitsFirstBlock = (this.blocks[this.blockPointer] & mask1) << (numBits - (this.bitPointer + 1));
89 | this.blockPointer++;
90 |
91 | var bitsSecondBlock = this.blocks[this.blockPointer] << (numBits - (this.bitPointer + 1 + 8));
92 | this.blockPointer++;
93 |
94 | for (var i = 0; i < numBits - (this.bitPointer + 1 + 8); i++)
95 | {
96 | mask3 += (1 << i);
97 | }
98 | mask3 <<= 8 - (numBits - (this.bitPointer + 1 + 8));
99 | var bitsThirdBlock = (this.blocks[this.blockPointer] & mask3) >> (8 - (numBits - (this.bitPointer + 1 + 8)));
100 |
101 | bits = bitsFirstBlock + bitsSecondBlock + bitsThirdBlock;
102 | this.bitPointer = this.bitPointer - (numBits - 8) % 8;
103 | if (this.bitPointer < 0)
104 | {
105 | this.bitPointer = 8 + this.bitPointer;
106 | }
107 | return bits;
108 | }
109 | else
110 | {
111 | return 0;
112 | }
113 | }
114 | this.NextMode=function()
115 | {
116 | if ((this.blockPointer > this.blocks.length - this.numErrorCorrectionCode - 2))
117 | return 0;
118 | else
119 | return this.getNextBits(4);
120 | }
121 | this.getDataLength=function( modeIndicator)
122 | {
123 | var index = 0;
124 | while (true)
125 | {
126 | if ((modeIndicator >> index) == 1)
127 | break;
128 | index++;
129 | }
130 |
131 | return this.getNextBits(qrcode.sizeOfDataLengthInfo[this.dataLengthMode][index]);
132 | }
133 | this.getRomanAndFigureString=function( dataLength)
134 | {
135 | var length = dataLength;
136 | var intData = 0;
137 | var strData = "";
138 | var tableRomanAndFigure = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':');
139 | do
140 | {
141 | if (length > 1)
142 | {
143 | intData = this.getNextBits(11);
144 | var firstLetter = Math.floor(intData / 45);
145 | var secondLetter = intData % 45;
146 | strData += tableRomanAndFigure[firstLetter];
147 | strData += tableRomanAndFigure[secondLetter];
148 | length -= 2;
149 | }
150 | else if (length == 1)
151 | {
152 | intData = this.getNextBits(6);
153 | strData += tableRomanAndFigure[intData];
154 | length -= 1;
155 | }
156 | }
157 | while (length > 0);
158 |
159 | return strData;
160 | }
161 | this.getFigureString=function( dataLength)
162 | {
163 | var length = dataLength;
164 | var intData = 0;
165 | var strData = "";
166 | do
167 | {
168 | if (length >= 3)
169 | {
170 | intData = this.getNextBits(10);
171 | if (intData < 100)
172 | strData += "0";
173 | if (intData < 10)
174 | strData += "0";
175 | length -= 3;
176 | }
177 | else if (length == 2)
178 | {
179 | intData = this.getNextBits(7);
180 | if (intData < 10)
181 | strData += "0";
182 | length -= 2;
183 | }
184 | else if (length == 1)
185 | {
186 | intData = this.getNextBits(4);
187 | length -= 1;
188 | }
189 | strData += intData;
190 | }
191 | while (length > 0);
192 |
193 | return strData;
194 | }
195 | this.get8bitByteArray=function( dataLength)
196 | {
197 | var length = dataLength;
198 | var intData = 0;
199 | var output = new Array();
200 |
201 | do
202 | {
203 | intData = this.getNextBits(8);
204 | output.push( intData);
205 | length--;
206 | }
207 | while (length > 0);
208 | return output;
209 | }
210 | this.getKanjiString=function( dataLength)
211 | {
212 | var length = dataLength;
213 | var intData = 0;
214 | var unicodeString = "";
215 | do
216 | {
217 | intData = getNextBits(13);
218 | var lowerByte = intData % 0xC0;
219 | var higherByte = intData / 0xC0;
220 |
221 | var tempWord = (higherByte << 8) + lowerByte;
222 | var shiftjisWord = 0;
223 | if (tempWord + 0x8140 <= 0x9FFC)
224 | {
225 | // between 8140 - 9FFC on Shift_JIS character set
226 | shiftjisWord = tempWord + 0x8140;
227 | }
228 | else
229 | {
230 | // between E040 - EBBF on Shift_JIS character set
231 | shiftjisWord = tempWord + 0xC140;
232 | }
233 |
234 | //var tempByte = new Array(0,0);
235 | //tempByte[0] = (sbyte) (shiftjisWord >> 8);
236 | //tempByte[1] = (sbyte) (shiftjisWord & 0xFF);
237 | //unicodeString += new String(SystemUtils.ToCharArray(SystemUtils.ToByteArray(tempByte)));
238 | unicodeString += String.fromCharCode(shiftjisWord);
239 | length--;
240 | }
241 | while (length > 0);
242 |
243 |
244 | return unicodeString;
245 | }
246 |
247 | this.__defineGetter__("DataByte", function()
248 | {
249 | var output = new Array();
250 | var MODE_NUMBER = 1;
251 | var MODE_ROMAN_AND_NUMBER = 2;
252 | var MODE_8BIT_BYTE = 4;
253 | var MODE_KANJI = 8;
254 | do
255 | {
256 | var mode = this.NextMode();
257 | //canvas.println("mode: " + mode);
258 | if (mode == 0)
259 | {
260 | if (output.length > 0)
261 | break;
262 | else
263 | throw "Empty data block";
264 | }
265 | //if (mode != 1 && mode != 2 && mode != 4 && mode != 8)
266 | // break;
267 | //}
268 | if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER && mode != MODE_8BIT_BYTE && mode != MODE_KANJI)
269 | {
270 | /* canvas.println("Invalid mode: " + mode);
271 | mode = guessMode(mode);
272 | canvas.println("Guessed mode: " + mode); */
273 | throw "Invalid mode: " + mode + " in (block:" + this.blockPointer + " bit:" + this.bitPointer + ")";
274 | }
275 | dataLength = this.getDataLength(mode);
276 | if (dataLength < 1)
277 | throw "Invalid data length: " + dataLength;
278 | //canvas.println("length: " + dataLength);
279 | switch (mode)
280 | {
281 |
282 | case MODE_NUMBER:
283 | //canvas.println("Mode: Figure");
284 | var temp_str = this.getFigureString(dataLength);
285 | var ta = new Array(temp_str.length);
286 | for(var j=0;j