From 4849cead45edf85cf2a61526c0b716eb637f74ba Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Mon, 1 Apr 2013 16:56:16 -0700 Subject: systrace: update to trace-viewer rev 243 Change-Id: I1ef3bcc7228d2f681ea3b08e9bd7af6175865dd5 --- UPSTREAM_REVISION | 2 +- script.js | 107 +++--- style.css | 2 +- trace-viewer/run_dev_server.py | 17 +- trace-viewer/src/about_tracing.html | 2 +- trace-viewer/src/about_tracing.js | 6 +- trace-viewer/src/deps.js | 18 +- trace-viewer/src/focus_outline_manager.js | 84 ----- .../src/importer/linux_perf/disk_parser.js | 177 ++++++++++ .../src/importer/linux_perf/disk_parser_test.html | 86 +++++ trace-viewer/src/importer/linux_perf_importer.js | 1 + trace-viewer/src/importer/trace_event_importer.js | 2 +- .../src/importer/trace_event_importer_test.html | 16 +- trace-viewer/src/profiling_view.js | 2 + trace-viewer/src/settings.js | 5 +- trace-viewer/src/settings_test.html | 2 +- trace-viewer/src/tests.html | 3 +- trace-viewer/src/timeline.js | 16 +- trace-viewer/src/tracks/canvas_based_track.js | 6 +- trace-viewer/src/tracks/ruler_track.css | 15 + trace-viewer/src/tracks/ruler_track.js | 358 +++++++++++++++++++++ trace-viewer/src/tracks/ruler_track_test.html | 41 +++ trace-viewer/src/tracks/viewport_track.css | 15 - trace-viewer/src/tracks/viewport_track.js | 358 --------------------- trace-viewer/src/tracks/viewport_track_test.html | 41 --- 25 files changed, 795 insertions(+), 587 deletions(-) delete mode 100644 trace-viewer/src/focus_outline_manager.js create mode 100644 trace-viewer/src/importer/linux_perf/disk_parser.js create mode 100644 trace-viewer/src/importer/linux_perf/disk_parser_test.html create mode 100644 trace-viewer/src/tracks/ruler_track.css create mode 100644 trace-viewer/src/tracks/ruler_track.js create mode 100644 trace-viewer/src/tracks/ruler_track_test.html delete mode 100644 trace-viewer/src/tracks/viewport_track.css delete mode 100644 trace-viewer/src/tracks/viewport_track.js delete mode 100644 trace-viewer/src/tracks/viewport_track_test.html diff --git a/UPSTREAM_REVISION b/UPSTREAM_REVISION index 997def45..2c2b1af8 100644 --- a/UPSTREAM_REVISION +++ b/UPSTREAM_REVISION @@ -1 +1 @@ -237 +245 diff --git a/script.js b/script.js index 559f1ddb..4dee3b62 100644 --- a/script.js +++ b/script.js @@ -1,17 +1,17 @@ window.FLATTENED={};window.FLATTENED.base=!0;window.FLATTENED.event_target=!0;window.FLATTENED.measuring_stick=!0;window.FLATTENED.filter=!0;window.FLATTENED.range=!0;window.FLATTENED.selection=!0;window.FLATTENED.timeline_viewport=!0;window.FLATTENED.ui=!0;window.FLATTENED["tracks.track"]=!0;window.FLATTENED["tracks.container_track"]=!0;window.FLATTENED.fast_rect_renderer=!0;window.FLATTENED.color_scheme=!0;window.FLATTENED["tracks.canvas_based_track"]=!0;window.FLATTENED.sorted_array_utils=!0; window.FLATTENED["tracks.slice_track"]=!0;window.FLATTENED.guid=!0;window.FLATTENED.slice=!0;window.FLATTENED.slice_group=!0;window.FLATTENED.async_slice_group=!0;window.FLATTENED.sample=!0;window.FLATTENED.thread=!0;window.FLATTENED.counter=!0;window.FLATTENED.process_base=!0;window.FLATTENED.process=!0;window.FLATTENED.kernel=!0;window.FLATTENED.cpu=!0;window.FLATTENED.model=!0;window.FLATTENED["tracks.cpu_track"]=!0;window.FLATTENED["tracks.counter_track"]=!0; -window.FLATTENED["tracks.slice_group_track"]=!0;window.FLATTENED["tracks.async_slice_group_track"]=!0;window.FLATTENED["tracks.thread_track"]=!0;window.FLATTENED["tracks.process_track"]=!0;window.FLATTENED["tracks.model_track"]=!0;window.FLATTENED["tracks.viewport_track"]=!0;window.FLATTENED.timeline=!0;window.FLATTENED["analysis.util"]=!0;window.FLATTENED.timeline_analysis_view=!0;window.FLATTENED.overlay=!0;window.FLATTENED.category_filter_dialog=!0;window.FLATTENED.find_control=!0; -window.FLATTENED["importer.trace_event_importer"]=!0;window.FLATTENED["importer.linux_perf.parser"]=!0;window.FLATTENED["importer.linux_perf.bus_parser"]=!0;window.FLATTENED["importer.linux_perf.clock_parser"]=!0;window.FLATTENED["importer.linux_perf.cpufreq_parser"]=!0;window.FLATTENED["importer.linux_perf.drm_parser"]=!0;window.FLATTENED["importer.linux_perf.exynos_parser"]=!0;window.FLATTENED["importer.linux_perf.gesture_parser"]=!0;window.FLATTENED["importer.linux_perf.i915_parser"]=!0; -window.FLATTENED["importer.linux_perf.mali_parser"]=!0;window.FLATTENED["importer.linux_perf.power_parser"]=!0;window.FLATTENED["importer.linux_perf.sched_parser"]=!0;window.FLATTENED["importer.linux_perf.workqueue_parser"]=!0;window.FLATTENED["importer.linux_perf.android_parser"]=!0;window.FLATTENED["importer.linux_perf_importer"]=!0;window.FLATTENED["importer.v8.log_reader"]=!0;window.FLATTENED["importer.v8.splaytree"]=!0;window.FLATTENED["importer.v8.codemap"]=!0; -window.FLATTENED["importer.v8_log_importer"]=!0;window.FLATTENED.settings=!0;window.FLATTENED.timeline_view=!0;"use strict";var global=this; +window.FLATTENED["tracks.slice_group_track"]=!0;window.FLATTENED["tracks.async_slice_group_track"]=!0;window.FLATTENED["tracks.thread_track"]=!0;window.FLATTENED["tracks.process_track"]=!0;window.FLATTENED["tracks.model_track"]=!0;window.FLATTENED["tracks.ruler_track"]=!0;window.FLATTENED.timeline=!0;window.FLATTENED["analysis.util"]=!0;window.FLATTENED.timeline_analysis_view=!0;window.FLATTENED.overlay=!0;window.FLATTENED.category_filter_dialog=!0;window.FLATTENED.find_control=!0; +window.FLATTENED["importer.trace_event_importer"]=!0;window.FLATTENED["importer.linux_perf.parser"]=!0;window.FLATTENED["importer.linux_perf.bus_parser"]=!0;window.FLATTENED["importer.linux_perf.clock_parser"]=!0;window.FLATTENED["importer.linux_perf.cpufreq_parser"]=!0;window.FLATTENED["importer.linux_perf.disk_parser"]=!0;window.FLATTENED["importer.linux_perf.drm_parser"]=!0;window.FLATTENED["importer.linux_perf.exynos_parser"]=!0;window.FLATTENED["importer.linux_perf.gesture_parser"]=!0; +window.FLATTENED["importer.linux_perf.i915_parser"]=!0;window.FLATTENED["importer.linux_perf.mali_parser"]=!0;window.FLATTENED["importer.linux_perf.power_parser"]=!0;window.FLATTENED["importer.linux_perf.sched_parser"]=!0;window.FLATTENED["importer.linux_perf.workqueue_parser"]=!0;window.FLATTENED["importer.linux_perf.android_parser"]=!0;window.FLATTENED["importer.linux_perf_importer"]=!0;window.FLATTENED["importer.v8.log_reader"]=!0;window.FLATTENED["importer.v8.splaytree"]=!0; +window.FLATTENED["importer.v8.codemap"]=!0;window.FLATTENED["importer.v8_log_importer"]=!0;window.FLATTENED.settings=!0;window.FLATTENED.timeline_view=!0;"use strict";var global=this; this.base=function(){function d(b){"/"==b[b.length-1]&&(b=b.substring(0,b.length-1));q=b}function c(b,a){r[b]||(r[b]=[]);for(var f=r[b],e=!1,g=0;g\x3c/script>';base.doc.write(h);v[d]="APPENDED"}}j=r[b]||[];for(k=0;k\x3c/script>'); +}else if(f(),"APPENDED"!=u[b]){if("RESOLVING"==u[b])throw Error("Circular dependency betwen modules. Cannot continue!");u[b]="RESOLVING";for(var j=t[b]||[],d=0;d\x3c/script>';base.doc.write(h);v[k]="APPENDED"}}j=r[b]||[];for(d=0;d\x3c/script>'); u[b]="APPENDED"}}function g(b){if(!window.FLATTENED&&!x[b]){x[b]=!0;b=b.replace(/\./g,"/")+".css";b=q+"/"+b;var a=document.createElement("link");a.setAttribute("rel","stylesheet");a.setAttribute("href",b);base.doc.head.appendChild(a)}}function j(b,a,f,e){var g=new base.Event(a+"Change");g.propertyName=a;g.newValue=f;g.oldValue=e;b.dispatchEvent(g)}function h(b){return b.replace(/([A-Z])/g,"-$1").toLowerCase()}function k(b,a){switch(a){case y.JS:var f=b+"_";return function(){return this[f]};case y.ATTR:var e= h(b);return function(){return this.getAttribute(e)};case y.BOOL_ATTR:return e=h(b),function(){return this.hasAttribute(e)}}}function l(b,a,f){switch(a){case y.JS:var e=b+"_";return function(a){var g=this[e];a!==g&&(this[e]=a,f&&f.call(this,a,g),j(this,b,a,g))};case y.ATTR:var g=h(b);return function(a){var e=this[g];a!==e&&(void 0==a?this.removeAttribute(g):this.setAttribute(g,a),f&&f.call(this,a,e),j(this,b,a,e))};case y.BOOL_ATTR:return g=h(b),function(a){var e=this[g];a!==e&&(a?this.setAttribute(g, b):this.removeAttribute(g),f&&f.call(this,a,e),j(this,b,a,e))}}}function w(b,a,f){var e=base.doc.createEvent("Event");e.initEvent(b,!!a,!!f);e.__proto__=global.Event.prototype;return e}function m(){this.types=[];this.values=[]}var q=".",p=!1,r={},t={},s={},u={},v={},x={},y={JS:"js",ATTR:"attr",BOOL_ATTR:"boolAttr"},z=1;m.prototype={__proto__:Object.prototype,add:function(b,a){this.types.push(b);this.values.push(a)},get:function(b){for(var a=0;athis.viewport_.markers.length?this.classList.remove("viewport-track-with-distance-measurements"):this.classList.add("viewport-track-with-distance-measurements")},invalidate:function(){this.rafPending_||(webkitRequestAnimationFrame(function(){this.rafPending_= +this.viewport_.addEventListener("markersChange",this.viewportMarkersChangeBoundToThis_),this.isAttachedToDocument_&&this.updateCanvasSizeIfNeeded_();this.invalidate()},viewportChange_:function(){this.invalidate()},viewportMarkersChange_:function(){2>this.viewport_.markers.length?this.classList.remove("ruler-track-with-distance-measurements"):this.classList.add("ruler-track-with-distance-measurements")},invalidate:function(){this.rafPending_||(webkitRequestAnimationFrame(function(){this.rafPending_= !1;this.viewport_&&(this.updateCanvasSizeIfNeeded_(),this.redraw())}.bind(this),this),this.rafPending_=!0)},get isAttachedToDocument_(){var c=this.parentNode;if(c){for(;c.parentNode;)c=c.parentNode;return c==this.ownerDocument}},updateCanvasSizeIfNeeded_:function(){var c=window.getComputedStyle(this.canvasContainer_),a=parseInt(c.width)-parseInt(c.paddingLeft)-parseInt(c.paddingRight)-parseInt(c.borderLeftWidth)-parseInt(c.borderRightWidth),c=parseInt(c.height)-parseInt(c.paddingTop)-parseInt(c.paddingBottom)- parseInt(c.borderTopWidth)-parseInt(c.borderBottomWidth),b=window.devicePixelRatio||1;this.canvas_.width!=a&&(this.canvas_.width=a*b,this.canvas_.style.width=a+"px");this.canvas_.height!=c&&(this.canvas_.height=c*b,this.canvas_.style.height=c+"px")},get firstCanvas(){return this.canvas_}};return{CanvasBasedTrack:d}}); base.exportTo("tracing",function(){function d(a,b,f){if(0==a.length)return 1;for(var e=0,g=a.length-1,c,d,k=-1;e<=g;)c=Math.floor((e+g)/2),d=b(a[c])-f,0>d?e=c+1:(0g)){var h=d(a,b,e);if(-1!=h&&(0=e&&c(a[h-1]),h!=a.length))for(f=a.length;h=g);h++)c(a[h])}}return{findLowIndexInSortedArray:d,findLowIndexInSortedIntervals:function(a,b,f,e){var g=d(a,b,e);return 0==g?e>=b(a[0])&&ea&&(a=e)}this.headingWidth=a+ -"px"},updateChildTracks_:function(){this.detachAllChildren();if(this.model_){var c=this.model_.getAllCpus();c.sort(tracing.Cpu.compare);for(var a=0;aq?(m="ms",p=1,r=this.strings_msecs_):(m="s",p=1E3,r=this.strings_secs_);var t=e.xWorldVectorToView(q/ +for(var g=e.xViewToWorld(0),d=e.xViewToWorld(b),h=this.classList.contains("ruler-track-with-distance-measurements"),k=h?f/2:f,l=0;lq?(m="ms",p=1,r=this.strings_msecs_):(m="s",p=1E3,r=this.strings_secs_);var t=e.xWorldVectorToView(q/ 5),l=Math.floor(g/q)*q,f=Math.floor(0.25*f);a.fillStyle="rgb(0, 0, 0)";a.strokeStyle="rgb(0, 0, 0)";a.textAlign="left";a.textBaseline="top";w=window.devicePixelRatio||1;a.font=9*w+"px sans-serif";for(g=l;gl;++l){var u=Math.floor(s+t*l);a.moveTo(u,k-f);a.lineTo(u,k)}a.stroke()}if(h){a.moveTo(0,k);a.lineTo(b,k);a.stroke();b=e.markers.slice(); b.sort(function(b,a){return b.positionWorld_-a.positionWorld_});k+=2;d=k+4;for(l=0;lt?(m="ms",p=1):(m="s",p=1E3),p=t/p,m=Math.abs(Math.floor(1E3*p)/1E3)+" "+m,p=a.measureText(m).width,f=e.xViewVectorToWorld(p),p=p+26+10,g=r.positionWorld+t/2-f/2,s=g+f,t=k,f=e.xWorldToView(g),g=e.xWorldToView(s),r=e.xWorldToView(r.positionWorld),w=e.xWorldToView(w.positionWorld),s=!1, -p<=q&&(a.fillStyle="rgb(0,0,0)",a.fillText(m,f,t),s=!0),26<=q&&(s?(m=f-10,p=g+10):p=m=h,this.drawArrow_(a,m,d,r,d,3,"rgb(128,121,121)"),this.drawArrow_(a,p,d,w,d,3,"rgb(128,121,121)"))}},addIntersectingItemsToSelection:function(){},addIntersectingItemsInRangeToSelection:function(){},addAllObjectsMatchingFilterToSelection:function(){}};return{ViewportTrack:d}});"use strict";base.requireStylesheet("timeline");base.require("event_target");base.require("measuring_stick");base.require("filter");base.require("selection"); -base.require("timeline_viewport");base.require("tracks.model_track");base.require("tracks.viewport_track");base.require("ui"); -base.exportTo("tracing",function(){var d=tracing.Selection,c=tracing.TimelineViewport,a=tracing.ui.define("div");a.prototype={__proto__:HTMLDivElement.prototype,model_:null,decorate:function(){this.classList.add("timeline");this.categoryFilter_=new tracing.CategoryFilter;this.viewport_=new c(this);this.viewportTrack_=new tracing.tracks.ViewportTrack;this.viewportTrack_.viewport=this.viewport_;this.appendChild(this.viewportTrack_);this.modelTrackContainer_=document.createElement("div");this.modelTrackContainer_.className= +p<=q&&(a.fillStyle="rgb(0,0,0)",a.fillText(m,f,t),s=!0),26<=q&&(s?(m=f-10,p=g+10):p=m=h,this.drawArrow_(a,m,d,r,d,3,"rgb(128,121,121)"),this.drawArrow_(a,p,d,w,d,3,"rgb(128,121,121)"))}},addIntersectingItemsToSelection:function(){},addIntersectingItemsInRangeToSelection:function(){},addAllObjectsMatchingFilterToSelection:function(){}};return{RulerTrack:d}});"use strict";base.requireStylesheet("timeline");base.require("event_target");base.require("measuring_stick");base.require("filter");base.require("selection"); +base.require("timeline_viewport");base.require("tracks.model_track");base.require("tracks.ruler_track");base.require("ui"); +base.exportTo("tracing",function(){var d=tracing.Selection,c=tracing.TimelineViewport,a=tracing.ui.define("div");a.prototype={__proto__:HTMLDivElement.prototype,model_:null,decorate:function(){this.classList.add("timeline");this.categoryFilter_=new tracing.CategoryFilter;this.viewport_=new c(this);this.rulerTrack_=new tracing.tracks.RulerTrack;this.rulerTrack_.viewport=this.viewport_;this.appendChild(this.rulerTrack_);this.modelTrackContainer_=document.createElement("div");this.modelTrackContainer_.className= "model-track-container";this.appendChild(this.modelTrackContainer_);this.modelTrack_=new tracing.tracks.ModelTrack;this.modelTrackContainer_.appendChild(this.modelTrack_);this.dragBox_=this.ownerDocument.createElement("div");this.dragBox_.className="drag-box";this.appendChild(this.dragBox_);this.hideDragBox_();this.bindEventListener_(document,"keypress",this.onKeypress_,this);this.bindEventListener_(document,"keydown",this.onKeydown_,this);this.bindEventListener_(document,"keyup",this.onKeyup_,this); this.bindEventListener_(document,"mousemove",this.onMouseMove_,this);this.bindEventListener_(document,"mouseup",this.onMouseUp_,this);this.addEventListener("mousewheel",this.onMouseWheel_);this.addEventListener("mousedown",this.onMouseDown_);this.addEventListener("dblclick",this.onDblClick_);this.lastMouseViewPos_={x:0,y:0};this.maxHeadingWidth_=0;this.selection_=new d},bindEventListener_:function(b,a,e,c){this.boundListeners_||(this.boundListeners_=[]);e=e.bind(c);this.boundListeners_.push({object:b, event:a,boundFunc:e});b.addEventListener(a,e)},detach:function(){this.modelTrack_.detach();for(var b=0;b : Select next event on current timeline\n":b+"General Navigation\n g/General : Shows grid at the start/end of the selected task\n <-,^TAB : Select previous event on current timeline\n ->, TAB : Select next event on current timeline\n";return b+"\nAlt + Scroll to zoom in/out\nDbl-click to zoom in; Shift dbl-click to zoom out\nf to zoom into selection\nz to reset zoom and pan to initial view\n"}, get selection(){return this.selection_},set selection(b){if(!(b instanceof d))throw Error("Expected Selection");var a;for(a=0;ac?(c=e.min+0.5*(e.max-e.min),e=5*(e.max-e.min),this.viewport_.xSetWorldBounds(c-0.5*e,c+0.5*e,this.firstCanvas.width)):this.viewport_.xPanWorldBoundsIntoView(e.min,e.max,this.firstCanvas.width)},get firstCanvas(){if(this.viewportTrack_)return this.viewportTrack_.firstCanvas;if(this.modelTrack_)return this.modelTrack_.firstCanvas},hideDragBox_:function(){this.dragBox_.style.left="-1000px";this.dragBox_.style.top="-1000px";this.dragBox_.style.width= -0;this.dragBox_.style.height=0},setDragBoxPosition_:function(b,a,e,c,d){var h=Math.min(b,e);b=Math.max(b,e);e=this.modelTrack_.getBoundingClientRect();d?(d=e.top,e=e.bottom):(d=Math.min(a,c),e=Math.max(a,c));a=d;c=h+(b-h);d=a+(e-d);var k=this.modelTrackContainer_.getBoundingClientRect();e=k.left;var l=k.top,w=k.right,k=k.bottom,m=parseInt(this.modelTrack_.headingWidth);e+=m;m={};h>w||ck||d=e.left&&b.clientX=e.top&&b.clientY=c.left&&b.clientXa||(e=4,b.shiftKey&&(e=1/e),this.zoomBy_(e),b.preventDefault())}};base.defineProperty(a,"model",base.PropertyKind.JS);return{Timeline:a}});"use strict";base.exportTo("tracing.analysis",function(){return{tsRound:function(d){return Math.round(1E3*d)/1E3}}});"use strict";base.require("analysis.util");base.require("ui");base.requireStylesheet("timeline_analysis_view"); +this.viewport_.xWorldVectorToView(e.max-e.min);a&&50>c?(c=e.min+0.5*(e.max-e.min),e=5*(e.max-e.min),this.viewport_.xSetWorldBounds(c-0.5*e,c+0.5*e,this.firstCanvas.width)):this.viewport_.xPanWorldBoundsIntoView(e.min,e.max,this.firstCanvas.width)},get firstCanvas(){if(this.rulerTrack_)return this.rulerTrack_.firstCanvas;if(this.modelTrack_)return this.modelTrack_.firstCanvas},hideDragBox_:function(){this.dragBox_.style.left="-1000px";this.dragBox_.style.top="-1000px";this.dragBox_.style.width=0;this.dragBox_.style.height= +0},setDragBoxPosition_:function(b,a,e,c,d){var h=Math.min(b,e);b=Math.max(b,e);e=this.modelTrack_.getBoundingClientRect();d?(d=e.top,e=e.bottom):(d=Math.min(a,c),e=Math.max(a,c));a=d;c=h+(b-h);d=a+(e-d);var k=this.modelTrackContainer_.getBoundingClientRect();e=k.left;var l=k.top,w=k.right,k=k.bottom,m=parseInt(this.modelTrack_.headingWidth);e+=m;m={};h>w||ck||d=e.left&&b.clientX=e.top&&b.clientY=c.left&&b.clientXa||(e=4,b.shiftKey&&(e=1/e),this.zoomBy_(e),b.preventDefault())}};base.defineProperty(a,"model",base.PropertyKind.JS);return{Timeline:a}});"use strict";base.exportTo("tracing.analysis",function(){return{tsRound:function(d){return Math.round(1E3*d)/1E3}}});"use strict";base.require("analysis.util");base.require("ui");base.requireStylesheet("timeline_analysis_view"); base.exportTo("tracing",function(){function d(b,a){var e=a.getSliceHitsAsSelection(),c=a.getCounterSampleHitsAsSelection();if(1==e.length){var d=e[0].slice,h=b.appendTable("analysis-slice-table",2);b.appendTableHeader(h,"Selected slice:");b.appendSummaryRow(h,"Title",d.title);d.category&&b.appendSummaryRow(h,"Category",d.category);b.appendSummaryRowTime(h,"Start",d.start);b.appendSummaryRowTime(h,"Duration",d.duration);d.durationInUserTime&&b.appendSummaryRowTime(h,"Duration (U)",d.durationInUserTime); var e=0,k;for(k in d.args)e+=1;if(0/.test(a))return d;var f=a.split("\n"),g=1;if(!c(/^ + + + + + diff --git a/trace-viewer/src/importer/linux_perf_importer.js b/trace-viewer/src/importer/linux_perf_importer.js index d70168bd..922156fc 100644 --- a/trace-viewer/src/importer/linux_perf_importer.js +++ b/trace-viewer/src/importer/linux_perf_importer.js @@ -23,6 +23,7 @@ base.require('color_scheme'); base.require('importer.linux_perf.bus_parser'); base.require('importer.linux_perf.clock_parser'); base.require('importer.linux_perf.cpufreq_parser'); +base.require('importer.linux_perf.disk_parser'); base.require('importer.linux_perf.drm_parser'); base.require('importer.linux_perf.exynos_parser'); base.require('importer.linux_perf.gesture_parser'); diff --git a/trace-viewer/src/importer/trace_event_importer.js b/trace-viewer/src/importer/trace_event_importer.js index 334ea52c..03210a72 100644 --- a/trace-viewer/src/importer/trace_event_importer.js +++ b/trace-viewer/src/importer/trace_event_importer.js @@ -196,7 +196,7 @@ base.exportTo('tracing.importer', function() { this.processAsyncEvent(eI, event); } else if (event.ph == 'T') { this.processAsyncEvent(eI, event); - } else if (event.ph == 'I') { + } else if (event.ph == 'I' || event.ph == 'i') { // Treat an Instant event as a duration 0 slice. // SliceTrack's redraw() knows how to handle this. var thread = this.model_.getOrCreateProcess(event.pid) diff --git a/trace-viewer/src/importer/trace_event_importer_test.html b/trace-viewer/src/importer/trace_event_importer_test.html index b6c75d09..53abb82b 100644 --- a/trace-viewer/src/importer/trace_event_importer_test.html +++ b/trace-viewer/src/importer/trace_event_importer_test.html @@ -384,18 +384,19 @@ function testImmediateParsing() { // recentering/zeroing doesn't clobber their timestamp. {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'}, {name: 'immediate', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 1, ph: 'I'}, + {name: 'slower', args: {}, pid: 1, ts: 4, cat: 'baz', tid: 1, ph: 'i'}, {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'E'} ]; var m = new tracing.Model(events, false); var p = m.processes[1]; var t = p.threads[1]; - assertEquals(2, t.slices.length); + assertEquals(3, t.slices.length); assertEquals(0.002, t.slices[0].start); assertEquals(0, t.slices[0].duration); - assertEquals(0.001, t.slices[1].start); - assertEquals(0.003, t.slices[1].duration); + assertEquals(0.004, t.slices[1].start); + assertEquals(0.001, t.slices[2].start); + assertEquals(0.003, t.slices[2].duration); - assertEquals(2, t.slices.length); var slice = findSliceNamed(t.slices, 'a'); assertEquals('a', slice.title); assertEquals('foo', slice.category); @@ -407,6 +408,13 @@ function testImmediateParsing() { assertEquals(0.002, immed.start); assertEquals(0, immed.duration); assertEquals(0, immed.subSlices.length); + + var slower = findSliceNamed(t.slices, 'slower'); + assertEquals('slower', slower.title); + assertEquals('baz', slower.category); + assertEquals(0.004, slower.start); + assertEquals(0, slower.duration); + assertEquals(0, slower.subSlices.length); } function testSimpleCounter() { diff --git a/trace-viewer/src/profiling_view.js b/trace-viewer/src/profiling_view.js index 30005cfc..724fe825 100644 --- a/trace-viewer/src/profiling_view.js +++ b/trace-viewer/src/profiling_view.js @@ -152,6 +152,8 @@ base.exportTo('tracing', function() { dlg.visible = true; this.categorySelectionDialog_ = dlg; + buttonEl.focus(); + setTimeout(function() { tc.removeEventListener('categoriesCollected', this.onCategoriesCollectedBoundToThis_); diff --git a/trace-viewer/src/settings.js b/trace-viewer/src/settings.js index 6be30662..dada58cf 100644 --- a/trace-viewer/src/settings.js +++ b/trace-viewer/src/settings.js @@ -48,7 +48,7 @@ base.exportTo('base', function() { get: function(key, opt_default, opt_namespace) { key = this.namespace_(key, opt_namespace); var val = this.storage_.getItem(key); - if (val === undefined) + if (val === null || val === undefined) return opt_default; return String(val); }, @@ -121,6 +121,9 @@ base.exportTo('base', function() { __proto__: Object.prototype, getItem: function(key) { + // LocalStorage returns null if the key isn't found, not undefined. + if (this[key] === undefined || this[key] === null) + return null; return this[key]; }, diff --git a/trace-viewer/src/settings_test.html b/trace-viewer/src/settings_test.html index 6c484cc0..ac57694c 100644 --- a/trace-viewer/src/settings_test.html +++ b/trace-viewer/src/settings_test.html @@ -52,7 +52,7 @@ function testGetUnset() { function testGetDefault() { var settings = new base.Settings(); - // Null should be returned if value isn't set. + // default_val should be returned if value isn't set. assertEquals('default_val', settings.get('my_key', 'default_val')); } diff --git a/trace-viewer/src/tests.html b/trace-viewer/src/tests.html index 23118401..122b2b66 100644 --- a/trace-viewer/src/tests.html +++ b/trace-viewer/src/tests.html @@ -28,6 +28,7 @@ found in the LICENSE file. 'importer/linux_perf/bus_parser_test.html', 'importer/linux_perf/clock_parser_test.html', 'importer/linux_perf/cpufreq_parser_test.html', + 'importer/linux_perf/disk_parser_test.html', 'importer/linux_perf/drm_parser_test.html', 'importer/linux_perf/exynos_parser_test.html', 'importer/linux_perf/gesture_parser_test.html', @@ -53,7 +54,7 @@ found in the LICENSE file. 'tracks/slice_group_track_test.html', 'tracks/slice_track_test.html', 'tracks/thread_track_test.html', - 'tracks/viewport_track_test.html', + 'tracks/ruler_track_test.html', 'analysis/counter_selection_analysis_test.html', 'analysis/selection_analysis_test.html', 'analysis/slice_selection_analysis_test.html', diff --git a/trace-viewer/src/timeline.js b/trace-viewer/src/timeline.js index 02c24338..118ce30e 100644 --- a/trace-viewer/src/timeline.js +++ b/trace-viewer/src/timeline.js @@ -24,7 +24,7 @@ base.require('filter'); base.require('selection'); base.require('timeline_viewport'); base.require('tracks.model_track'); -base.require('tracks.viewport_track'); +base.require('tracks.ruler_track'); base.require('ui'); base.exportTo('tracing', function() { @@ -71,9 +71,9 @@ base.exportTo('tracing', function() { this.viewport_ = new Viewport(this); // Add the viewport track. - this.viewportTrack_ = new tracing.tracks.ViewportTrack(); - this.viewportTrack_.viewport = this.viewport_; - this.appendChild(this.viewportTrack_); + this.rulerTrack_ = new tracing.tracks.RulerTrack(); + this.rulerTrack_.viewport = this.viewport_; + this.appendChild(this.rulerTrack_); this.modelTrackContainer_ = document.createElement('div'); this.modelTrackContainer_.className = 'model-track-container'; @@ -155,7 +155,7 @@ base.exportTo('tracing', function() { this.modelTrack_.model = model; this.modelTrack_.viewport = this.viewport_; this.modelTrack_.categoryFilter = this.categoryFilter; - this.viewportTrack_.headingWidth = this.modelTrack_.headingWidth; + this.rulerTrack_.headingWidth = this.modelTrack_.headingWidth; // Set up a reasonable viewport. if (modelInstanceChanged) @@ -448,8 +448,8 @@ base.exportTo('tracing', function() { }, get firstCanvas() { - if (this.viewportTrack_) - return this.viewportTrack_.firstCanvas; + if (this.rulerTrack_) + return this.rulerTrack_.firstCanvas; if (this.modelTrack_) return this.modelTrack_.firstCanvas; return undefined; @@ -548,7 +548,7 @@ base.exportTo('tracing', function() { return; if (e.shiftKey) { - this.viewportTrack_.placeAndBeginDraggingMarker(e.clientX); + this.rulerTrack_.placeAndBeginDraggingMarker(e.clientX); return; } diff --git a/trace-viewer/src/tracks/canvas_based_track.js b/trace-viewer/src/tracks/canvas_based_track.js index 805d3702..f88058b3 100644 --- a/trace-viewer/src/tracks/canvas_based_track.js +++ b/trace-viewer/src/tracks/canvas_based_track.js @@ -102,11 +102,9 @@ base.exportTo('tracing.tracks', function() { viewportMarkersChange_: function() { if (this.viewport_.markers.length < 2) - this.classList.remove('viewport-track-with' + - '-distance-measurements'); + this.classList.remove('ruler-track-with-distance-measurements'); else - this.classList.add('viewport-track-with' + - '-distance-measurements'); + this.classList.add('ruler-track-with-distance-measurements'); }, invalidate: function() { diff --git a/trace-viewer/src/tracks/ruler_track.css b/trace-viewer/src/tracks/ruler_track.css new file mode 100644 index 00000000..9204bb61 --- /dev/null +++ b/trace-viewer/src/tracks/ruler_track.css @@ -0,0 +1,15 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +.ruler-track { + height: 12px; +} + +.ruler-track-with-distance-measurements { + height: 24px; +} + +.ruler-track .canvas-based-track-canvas-container { + border-bottom: 1px solid #8e8e8e; +} diff --git a/trace-viewer/src/tracks/ruler_track.js b/trace-viewer/src/tracks/ruler_track.js new file mode 100644 index 00000000..1e78661a --- /dev/null +++ b/trace-viewer/src/tracks/ruler_track.js @@ -0,0 +1,358 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +base.requireStylesheet('tracks.ruler_track'); + +base.require('tracks.track'); +base.require('tracks.canvas_based_track'); +base.require('ui'); + +base.exportTo('tracing.tracks', function() { + + /** + * A track that displays the ruler. + * @constructor + * @extends {CanvasBasedTrack} + */ + + var RulerTrack = tracing.ui.define(tracing.tracks.CanvasBasedTrack); + + var logOf10 = Math.log(10); + function log10(x) { + return Math.log(x) / logOf10; + } + + RulerTrack.prototype = { + + __proto__: tracing.tracks.CanvasBasedTrack.prototype, + + decorate: function() { + this.classList.add('ruler-track'); + this.strings_secs_ = []; + this.strings_msecs_ = []; + this.addEventListener('mousedown', this.onMouseDown); + }, + + onMouseDown: function(e) { + if (e.button != 0) + return; + this.placeAndBeginDraggingMarker(e.clientX); + }, + + + placeAndBeginDraggingMarker: function(clientX) { + var pixelRatio = window.devicePixelRatio || 1; + var viewX = (clientX - this.canvasContainer_.offsetLeft) * pixelRatio; + var worldX = this.viewport_.xViewToWorld(viewX); + var marker = this.viewport_.findMarkerNear(worldX, 6); + var createdMarker = false; + var movedMarker = false; + if (!marker) { + marker = this.viewport_.addMarker(worldX); + createdMarker = true; + } + marker.selected = true; + + var that = this; + var onMouseMove = function(e) { + var viewX = (e.clientX - that.canvasContainer_.offsetLeft) * pixelRatio; + var worldX = that.viewport_.xViewToWorld(viewX); + marker.positionWorld = worldX; + movedMarker = true; + }; + + var onMouseUp = function(e) { + marker.selected = false; + if (!movedMarker && !createdMarker) + that.viewport_.removeMarker(marker); + document.removeEventListener('mouseup', onMouseUp); + document.removeEventListener('mousemove', onMouseMove); + }; + + document.addEventListener('mouseup', onMouseUp); + document.addEventListener('mousemove', onMouseMove); + }, + + drawLine_: function(ctx, x1, y1, x2, y2, color) { + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + ctx.strokeStyle = color; + ctx.stroke(); + }, + + drawArrow_: function(ctx, x1, y1, x2, y2, arrowWidth, color) { + + this.drawLine_(ctx, x1, y1, x2, y2, color); + + var dx = x2 - x1; + var dy = y2 - y1; + var len = Math.sqrt(dx * dx + dy * dy); + var perc = (len - 10) / len; + var bx = x1 + perc * dx; + var by = y1 + perc * dy; + var ux = dx / len; + var uy = dy / len; + var ax = uy * arrowWidth; + var ay = -ux * arrowWidth; + + ctx.beginPath(); + ctx.fillStyle = color; + ctx.moveTo(bx + ax, by + ay); + ctx.lineTo(x2, y2); + ctx.lineTo(bx - ax, by - ay); + ctx.lineTo(bx + ax, by + ay); + ctx.closePath(); + ctx.fill(); + }, + + redraw: function() { + var ctx = this.ctx_; + var canvasW = this.canvas_.width; + var canvasH = this.canvas_.height; + + ctx.clearRect(0, 0, canvasW, canvasH); + + // Culling parametrs. + var vp = this.viewport_; + var pixWidth = vp.xViewVectorToWorld(1); + var viewLWorld = vp.xViewToWorld(0); + var viewRWorld = vp.xViewToWorld(canvasW); + + var measurements = this.classList.contains( + 'ruler-track-with-distance-measurements'); + + var rulerHeight = measurements ? canvasH / 2 : canvasH; + + for (var i = 0; i < vp.markers.length; ++i) { + vp.markers[i].drawTriangle_(ctx, viewLWorld, viewRWorld, + canvasH, rulerHeight, vp); + } + + var pixelRatio = window.devicePixelRatio || 1; + var idealMajorMarkDistancePix = 150 * pixelRatio; + var idealMajorMarkDistanceWorld = + vp.xViewVectorToWorld(idealMajorMarkDistancePix); + + var majorMarkDistanceWorld; + var unit; + var unitDivisor; + var tickLabels; + + // The conservative guess is the nearest enclosing 0.1, 1, 10, 100, etc. + var conservativeGuess = + Math.pow(10, Math.ceil(log10(idealMajorMarkDistanceWorld))); + + // Once we have a conservative guess, consider things that evenly add up + // to the conservative guess, e.g. 0.5, 0.2, 0.1 Pick the one that still + // exceeds the ideal mark distance. + var divisors = [10, 5, 2, 1]; + for (var i = 0; i < divisors.length; ++i) { + var tightenedGuess = conservativeGuess / divisors[i]; + if (vp.xWorldVectorToView(tightenedGuess) < idealMajorMarkDistancePix) + continue; + majorMarkDistanceWorld = conservativeGuess / divisors[i - 1]; + break; + } + var tickLabels = undefined; + if (majorMarkDistanceWorld < 100) { + unit = 'ms'; + unitDivisor = 1; + tickLabels = this.strings_msecs_; + } else { + unit = 's'; + unitDivisor = 1000; + tickLabels = this.strings_secs_; + } + + var numTicksPerMajor = 5; + var minorMarkDistanceWorld = majorMarkDistanceWorld / numTicksPerMajor; + var minorMarkDistancePx = vp.xWorldVectorToView(minorMarkDistanceWorld); + + var firstMajorMark = + Math.floor(viewLWorld / majorMarkDistanceWorld) * + majorMarkDistanceWorld; + + var minorTickH = Math.floor(canvasH * 0.25); + + ctx.fillStyle = 'rgb(0, 0, 0)'; + ctx.strokeStyle = 'rgb(0, 0, 0)'; + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; + + var pixelRatio = window.devicePixelRatio || 1; + ctx.font = (9 * pixelRatio) + 'px sans-serif'; + + // Each iteration of this loop draws one major mark + // and numTicksPerMajor minor ticks. + // + // Rendering can't be done in world space because canvas transforms + // affect line width. So, do the conversions manually. + for (var curX = firstMajorMark; + curX < viewRWorld; + curX += majorMarkDistanceWorld) { + + var curXView = Math.floor(vp.xWorldToView(curX)); + + var unitValue = curX / unitDivisor; + var roundedUnitValue = Math.floor(unitValue * 100000) / 100000; + + if (!tickLabels[roundedUnitValue]) + tickLabels[roundedUnitValue] = roundedUnitValue + ' ' + unit; + ctx.fillText(tickLabels[roundedUnitValue], + curXView + 2 * pixelRatio, 0); + ctx.beginPath(); + + // Major mark + ctx.moveTo(curXView, 0); + ctx.lineTo(curXView, rulerHeight); + + // Minor marks + for (var i = 1; i < numTicksPerMajor; ++i) { + var xView = Math.floor(curXView + minorMarkDistancePx * i); + ctx.moveTo(xView, rulerHeight - minorTickH); + ctx.lineTo(xView, rulerHeight); + } + + ctx.stroke(); + } + + // Give distance between directly adjacent markers. + if (measurements) { + + // Divide canvas horizontally between ruler and measurements. + ctx.moveTo(0, rulerHeight); + ctx.lineTo(canvasW, rulerHeight); + ctx.stroke(); + + // Obtain a sorted array of markers + var sortedMarkers = vp.markers.slice(); + sortedMarkers.sort(function(a, b) { + return a.positionWorld_ - b.positionWorld_; + }); + + // Distance Variables. + var displayDistance; + var unitDivisor; + var displayTextColor = 'rgb(0,0,0)'; + var measurementsPosY = rulerHeight + 2; + + // Arrow Variables. + var arrowSpacing = 10; + var arrowColor = 'rgb(128,121,121)'; + var arrowPosY = measurementsPosY + 4; + var arrowWidthView = 3; + var spaceForArrowsView = 2 * (arrowWidthView + arrowSpacing); + + for (i = 0; i < sortedMarkers.length - 1; i++) { + var rightMarker = sortedMarkers[i + 1]; + var leftMarker = sortedMarkers[i]; + var distanceBetweenMarkers = + rightMarker.positionWorld - leftMarker.positionWorld; + var distanceBetweenMarkersView = + vp.xWorldVectorToView(distanceBetweenMarkers); + + var positionInMiddleOfMarkers = leftMarker.positionWorld + + distanceBetweenMarkers / 2; + var positionInMiddleOfMarkersView = + vp.xWorldToView(positionInMiddleOfMarkers); + + // Determine units. + if (distanceBetweenMarkers < 100) { + unit = 'ms'; + unitDivisor = 1; + } else { + unit = 's'; + unitDivisor = 1000; + } + // Calculate display value to print. + displayDistance = distanceBetweenMarkers / unitDivisor; + var roundedDisplayDistance = + Math.abs((Math.floor(displayDistance * 1000) / 1000)); + var textToDraw = roundedDisplayDistance + ' ' + unit; + var textWidthView = ctx.measureText(textToDraw).width; + var textWidthWorld = vp.xViewVectorToWorld(textWidthView); + var spaceForArrowsAndTextView = textWidthView + + spaceForArrowsView + arrowSpacing; + + // Set text positions. + var textLeft = leftMarker.positionWorld + + (distanceBetweenMarkers / 2) - (textWidthWorld / 2); + var textRight = textLeft + textWidthWorld; + var textPosY = measurementsPosY; + var textLeftView = vp.xWorldToView(textLeft); + var textRightView = vp.xWorldToView(textRight); + var leftMarkerView = vp.xWorldToView(leftMarker.positionWorld); + var rightMarkerView = vp.xWorldToView(rightMarker.positionWorld); + var textDrawn = false; + + if (spaceForArrowsAndTextView <= distanceBetweenMarkersView) { + // Print the display distance text. + ctx.fillStyle = displayTextColor; + ctx.fillText(textToDraw, textLeftView, textPosY); + textDrawn = true; + } + + if (spaceForArrowsView <= distanceBetweenMarkersView) { + var leftArrowStart; + var rightArrowStart; + if (textDrawn) { + leftArrowStart = textLeftView - arrowSpacing; + rightArrowStart = textRightView + arrowSpacing; + } else { + leftArrowStart = positionInMiddleOfMarkersView; + rightArrowStart = positionInMiddleOfMarkersView; + } + // Draw left arrow. + this.drawArrow_(ctx, leftArrowStart, arrowPosY, + leftMarkerView, arrowPosY, arrowWidthView, arrowColor); + // Draw right arrow. + this.drawArrow_(ctx, rightArrowStart, arrowPosY, + rightMarkerView, arrowPosY, arrowWidthView, arrowColor); + } + } + } + }, + + /** + * Adds items intersecting a point to a selection. + * @param {number} vX X location to search at, in viewspace. + * @param {number} vY Y location to search at, in viewspace. + * @param {Selection} selection Selection to which to add hits. + * @return {boolean} true if a slice was found, otherwise false. + */ + addIntersectingItemsToSelection: function(vX, vY, selection) { + // Does nothing. There's nothing interesting to pick on the ruler + // track. + }, + + /** + * Adds items intersecting the given range to a selection. + * @param {number} loVX Lower X bound of the interval to search, in + * viewspace. + * @param {number} hiVX Upper X bound of the interval to search, in + * viewspace. + * @param {number} loVY Lower Y bound of the interval to search, in + * viewspace. + * @param {number} hiVY Upper Y bound of the interval to search, in + * viewspace. + * @param {Selection} selection Selection to which to add hits. + */ + addIntersectingItemsInRangeToSelection: function( + loVX, hiVX, loY, hiY, selection) { + // Does nothing. There's nothing interesting to pick on the ruler + // track. + }, + + addAllObjectsMatchingFilterToSelection: function(filter, selection) { + } + }; + + return { + RulerTrack: RulerTrack + }; +}); diff --git a/trace-viewer/src/tracks/ruler_track_test.html b/trace-viewer/src/tracks/ruler_track_test.html new file mode 100644 index 00000000..908458e2 --- /dev/null +++ b/trace-viewer/src/tracks/ruler_track_test.html @@ -0,0 +1,41 @@ + + + + +Track tests + + + + + + + + diff --git a/trace-viewer/src/tracks/viewport_track.css b/trace-viewer/src/tracks/viewport_track.css deleted file mode 100644 index f7833567..00000000 --- a/trace-viewer/src/tracks/viewport_track.css +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -.viewport-track { - height: 12px; -} - -.viewport-track-with-distance-measurements { - height: 24px; -} - -.viewport-track .canvas-based-track-canvas-container { - border-bottom: 1px solid #8e8e8e; -} diff --git a/trace-viewer/src/tracks/viewport_track.js b/trace-viewer/src/tracks/viewport_track.js deleted file mode 100644 index 800f467d..00000000 --- a/trace-viewer/src/tracks/viewport_track.js +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -'use strict'; - -base.requireStylesheet('tracks.viewport_track'); - -base.require('tracks.track'); -base.require('tracks.canvas_based_track'); -base.require('ui'); - -base.exportTo('tracing.tracks', function() { - - /** - * A track that displays the viewport size and scale. - * @constructor - * @extends {CanvasBasedTrack} - */ - - var ViewportTrack = tracing.ui.define(tracing.tracks.CanvasBasedTrack); - - var logOf10 = Math.log(10); - function log10(x) { - return Math.log(x) / logOf10; - } - - ViewportTrack.prototype = { - - __proto__: tracing.tracks.CanvasBasedTrack.prototype, - - decorate: function() { - this.classList.add('viewport-track'); - this.strings_secs_ = []; - this.strings_msecs_ = []; - this.addEventListener('mousedown', this.onMouseDown); - }, - - onMouseDown: function(e) { - if (e.button != 0) - return; - this.placeAndBeginDraggingMarker(e.clientX); - }, - - - placeAndBeginDraggingMarker: function(clientX) { - var pixelRatio = window.devicePixelRatio || 1; - var viewX = (clientX - this.canvasContainer_.offsetLeft) * pixelRatio; - var worldX = this.viewport_.xViewToWorld(viewX); - var marker = this.viewport_.findMarkerNear(worldX, 6); - var createdMarker = false; - var movedMarker = false; - if (!marker) { - marker = this.viewport_.addMarker(worldX); - createdMarker = true; - } - marker.selected = true; - - var that = this; - var onMouseMove = function(e) { - var viewX = (e.clientX - that.canvasContainer_.offsetLeft) * pixelRatio; - var worldX = that.viewport_.xViewToWorld(viewX); - marker.positionWorld = worldX; - movedMarker = true; - }; - - var onMouseUp = function(e) { - marker.selected = false; - if (!movedMarker && !createdMarker) - that.viewport_.removeMarker(marker); - document.removeEventListener('mouseup', onMouseUp); - document.removeEventListener('mousemove', onMouseMove); - }; - - document.addEventListener('mouseup', onMouseUp); - document.addEventListener('mousemove', onMouseMove); - }, - - drawLine_: function(ctx, x1, y1, x2, y2, color) { - ctx.beginPath(); - ctx.moveTo(x1, y1); - ctx.lineTo(x2, y2); - ctx.closePath(); - ctx.strokeStyle = color; - ctx.stroke(); - }, - - drawArrow_: function(ctx, x1, y1, x2, y2, arrowWidth, color) { - - this.drawLine_(ctx, x1, y1, x2, y2, color); - - var dx = x2 - x1; - var dy = y2 - y1; - var len = Math.sqrt(dx * dx + dy * dy); - var perc = (len - 10) / len; - var bx = x1 + perc * dx; - var by = y1 + perc * dy; - var ux = dx / len; - var uy = dy / len; - var ax = uy * arrowWidth; - var ay = -ux * arrowWidth; - - ctx.beginPath(); - ctx.fillStyle = color; - ctx.moveTo(bx + ax, by + ay); - ctx.lineTo(x2, y2); - ctx.lineTo(bx - ax, by - ay); - ctx.lineTo(bx + ax, by + ay); - ctx.closePath(); - ctx.fill(); - }, - - redraw: function() { - var ctx = this.ctx_; - var canvasW = this.canvas_.width; - var canvasH = this.canvas_.height; - - ctx.clearRect(0, 0, canvasW, canvasH); - - // Culling parametrs. - var vp = this.viewport_; - var pixWidth = vp.xViewVectorToWorld(1); - var viewLWorld = vp.xViewToWorld(0); - var viewRWorld = vp.xViewToWorld(canvasW); - - var measurements = this.classList.contains('viewport' + - '-track-with-distance-measurements'); - - var rulerHeight = measurements ? canvasH / 2 : canvasH; - - for (var i = 0; i < vp.markers.length; ++i) { - vp.markers[i].drawTriangle_(ctx, viewLWorld, viewRWorld, - canvasH, rulerHeight, vp); - } - - var pixelRatio = window.devicePixelRatio || 1; - var idealMajorMarkDistancePix = 150 * pixelRatio; - var idealMajorMarkDistanceWorld = - vp.xViewVectorToWorld(idealMajorMarkDistancePix); - - var majorMarkDistanceWorld; - var unit; - var unitDivisor; - var tickLabels; - - // The conservative guess is the nearest enclosing 0.1, 1, 10, 100, etc. - var conservativeGuess = - Math.pow(10, Math.ceil(log10(idealMajorMarkDistanceWorld))); - - // Once we have a conservative guess, consider things that evenly add up - // to the conservative guess, e.g. 0.5, 0.2, 0.1 Pick the one that still - // exceeds the ideal mark distance. - var divisors = [10, 5, 2, 1]; - for (var i = 0; i < divisors.length; ++i) { - var tightenedGuess = conservativeGuess / divisors[i]; - if (vp.xWorldVectorToView(tightenedGuess) < idealMajorMarkDistancePix) - continue; - majorMarkDistanceWorld = conservativeGuess / divisors[i - 1]; - break; - } - var tickLabels = undefined; - if (majorMarkDistanceWorld < 100) { - unit = 'ms'; - unitDivisor = 1; - tickLabels = this.strings_msecs_; - } else { - unit = 's'; - unitDivisor = 1000; - tickLabels = this.strings_secs_; - } - - var numTicksPerMajor = 5; - var minorMarkDistanceWorld = majorMarkDistanceWorld / numTicksPerMajor; - var minorMarkDistancePx = vp.xWorldVectorToView(minorMarkDistanceWorld); - - var firstMajorMark = - Math.floor(viewLWorld / majorMarkDistanceWorld) * - majorMarkDistanceWorld; - - var minorTickH = Math.floor(canvasH * 0.25); - - ctx.fillStyle = 'rgb(0, 0, 0)'; - ctx.strokeStyle = 'rgb(0, 0, 0)'; - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; - - var pixelRatio = window.devicePixelRatio || 1; - ctx.font = (9 * pixelRatio) + 'px sans-serif'; - - // Each iteration of this loop draws one major mark - // and numTicksPerMajor minor ticks. - // - // Rendering can't be done in world space because canvas transforms - // affect line width. So, do the conversions manually. - for (var curX = firstMajorMark; - curX < viewRWorld; - curX += majorMarkDistanceWorld) { - - var curXView = Math.floor(vp.xWorldToView(curX)); - - var unitValue = curX / unitDivisor; - var roundedUnitValue = Math.floor(unitValue * 100000) / 100000; - - if (!tickLabels[roundedUnitValue]) - tickLabels[roundedUnitValue] = roundedUnitValue + ' ' + unit; - ctx.fillText(tickLabels[roundedUnitValue], - curXView + 2 * pixelRatio, 0); - ctx.beginPath(); - - // Major mark - ctx.moveTo(curXView, 0); - ctx.lineTo(curXView, rulerHeight); - - // Minor marks - for (var i = 1; i < numTicksPerMajor; ++i) { - var xView = Math.floor(curXView + minorMarkDistancePx * i); - ctx.moveTo(xView, rulerHeight - minorTickH); - ctx.lineTo(xView, rulerHeight); - } - - ctx.stroke(); - } - - // Give distance between directly adjacent markers. - if (measurements) { - - // Divide canvas horizontally between ruler and measurements. - ctx.moveTo(0, rulerHeight); - ctx.lineTo(canvasW, rulerHeight); - ctx.stroke(); - - // Obtain a sorted array of markers - var sortedMarkers = vp.markers.slice(); - sortedMarkers.sort(function(a, b) { - return a.positionWorld_ - b.positionWorld_; - }); - - // Distance Variables. - var displayDistance; - var unitDivisor; - var displayTextColor = 'rgb(0,0,0)'; - var measurementsPosY = rulerHeight + 2; - - // Arrow Variables. - var arrowSpacing = 10; - var arrowColor = 'rgb(128,121,121)'; - var arrowPosY = measurementsPosY + 4; - var arrowWidthView = 3; - var spaceForArrowsView = 2 * (arrowWidthView + arrowSpacing); - - for (i = 0; i < sortedMarkers.length - 1; i++) { - var rightMarker = sortedMarkers[i + 1]; - var leftMarker = sortedMarkers[i]; - var distanceBetweenMarkers = - rightMarker.positionWorld - leftMarker.positionWorld; - var distanceBetweenMarkersView = - vp.xWorldVectorToView(distanceBetweenMarkers); - - var positionInMiddleOfMarkers = leftMarker.positionWorld + - distanceBetweenMarkers / 2; - var positionInMiddleOfMarkersView = - vp.xWorldToView(positionInMiddleOfMarkers); - - // Determine units. - if (distanceBetweenMarkers < 100) { - unit = 'ms'; - unitDivisor = 1; - } else { - unit = 's'; - unitDivisor = 1000; - } - // Calculate display value to print. - displayDistance = distanceBetweenMarkers / unitDivisor; - var roundedDisplayDistance = - Math.abs((Math.floor(displayDistance * 1000) / 1000)); - var textToDraw = roundedDisplayDistance + ' ' + unit; - var textWidthView = ctx.measureText(textToDraw).width; - var textWidthWorld = vp.xViewVectorToWorld(textWidthView); - var spaceForArrowsAndTextView = textWidthView + - spaceForArrowsView + arrowSpacing; - - // Set text positions. - var textLeft = leftMarker.positionWorld + - (distanceBetweenMarkers / 2) - (textWidthWorld / 2); - var textRight = textLeft + textWidthWorld; - var textPosY = measurementsPosY; - var textLeftView = vp.xWorldToView(textLeft); - var textRightView = vp.xWorldToView(textRight); - var leftMarkerView = vp.xWorldToView(leftMarker.positionWorld); - var rightMarkerView = vp.xWorldToView(rightMarker.positionWorld); - var textDrawn = false; - - if (spaceForArrowsAndTextView <= distanceBetweenMarkersView) { - // Print the display distance text. - ctx.fillStyle = displayTextColor; - ctx.fillText(textToDraw, textLeftView, textPosY); - textDrawn = true; - } - - if (spaceForArrowsView <= distanceBetweenMarkersView) { - var leftArrowStart; - var rightArrowStart; - if (textDrawn) { - leftArrowStart = textLeftView - arrowSpacing; - rightArrowStart = textRightView + arrowSpacing; - } else { - leftArrowStart = positionInMiddleOfMarkersView; - rightArrowStart = positionInMiddleOfMarkersView; - } - // Draw left arrow. - this.drawArrow_(ctx, leftArrowStart, arrowPosY, - leftMarkerView, arrowPosY, arrowWidthView, arrowColor); - // Draw right arrow. - this.drawArrow_(ctx, rightArrowStart, arrowPosY, - rightMarkerView, arrowPosY, arrowWidthView, arrowColor); - } - } - } - }, - - /** - * Adds items intersecting a point to a selection. - * @param {number} vX X location to search at, in viewspace. - * @param {number} vY Y location to search at, in viewspace. - * @param {Selection} selection Selection to which to add hits. - * @return {boolean} true if a slice was found, otherwise false. - */ - addIntersectingItemsToSelection: function(vX, vY, selection) { - // Does nothing. There's nothing interesting to pick on the viewport - // track. - }, - - /** - * Adds items intersecting the given range to a selection. - * @param {number} loVX Lower X bound of the interval to search, in - * viewspace. - * @param {number} hiVX Upper X bound of the interval to search, in - * viewspace. - * @param {number} loVY Lower Y bound of the interval to search, in - * viewspace. - * @param {number} hiVY Upper Y bound of the interval to search, in - * viewspace. - * @param {Selection} selection Selection to which to add hits. - */ - addIntersectingItemsInRangeToSelection: function( - loVX, hiVX, loY, hiY, selection) { - // Does nothing. There's nothing interesting to pick on the viewport - // track. - }, - - addAllObjectsMatchingFilterToSelection: function(filter, selection) { - } - }; - - return { - ViewportTrack: ViewportTrack - }; -}); diff --git a/trace-viewer/src/tracks/viewport_track_test.html b/trace-viewer/src/tracks/viewport_track_test.html deleted file mode 100644 index 3e0a1f52..00000000 --- a/trace-viewer/src/tracks/viewport_track_test.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - -Track tests - - - - - - - - -- cgit v1.2.3