Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js

Issue 2850793004: DevTools: Support arbitrary bar heights on flamechart (Closed)
Patch Set: 4 landing Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartDataProvider.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /** 1 /**
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 this._windowLeft = 0.0; 84 this._windowLeft = 0.0;
85 this._windowRight = 1.0; 85 this._windowRight = 1.0;
86 this._timeWindowLeft = 0; 86 this._timeWindowLeft = 0;
87 this._timeWindowRight = Infinity; 87 this._timeWindowRight = Infinity;
88 this._rangeSelectionStart = 0; 88 this._rangeSelectionStart = 0;
89 this._rangeSelectionEnd = 0; 89 this._rangeSelectionEnd = 0;
90 this._barHeight = 17; 90 this._barHeight = 17;
91 this._textBaseline = 5; 91 this._textBaseline = 5;
92 this._textPadding = 5; 92 this._textPadding = 5;
93 this._paddingLeft = 0; 93 this._paddingLeft = 0;
94 var markerPadding = 2; 94 this._markerRadius = 6;
95 this._markerRadius = this._barHeight / 2 - markerPadding;
96 95
97 /** @const */ 96 /** @const */
98 this._headerLeftPadding = 6; 97 this._headerLeftPadding = 6;
99 /** @const */ 98 /** @const */
100 this._arrowSide = 8; 99 this._arrowSide = 8;
101 /** @const */ 100 /** @const */
102 this._expansionArrowIndent = this._headerLeftPadding + this._arrowSide / 2; 101 this._expansionArrowIndent = this._headerLeftPadding + this._arrowSide / 2;
103 /** @const */ 102 /** @const */
104 this._headerLabelXPadding = 3; 103 this._headerLabelXPadding = 3;
105 /** @const */ 104 /** @const */
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 if (!timelineData) 202 if (!timelineData)
204 return; 203 return;
205 // Think in terms of not where we are, but where we'll be after animation (i f present) 204 // Think in terms of not where we are, but where we'll be after animation (i f present)
206 var timeLeft = this._cancelWindowTimesAnimation ? this._pendingAnimationTime Left : this._timeWindowLeft; 205 var timeLeft = this._cancelWindowTimesAnimation ? this._pendingAnimationTime Left : this._timeWindowLeft;
207 var timeRight = this._cancelWindowTimesAnimation ? this._pendingAnimationTim eRight : this._timeWindowRight; 206 var timeRight = this._cancelWindowTimesAnimation ? this._pendingAnimationTim eRight : this._timeWindowRight;
208 var entryStartTime = timelineData.entryStartTimes[entryIndex]; 207 var entryStartTime = timelineData.entryStartTimes[entryIndex];
209 var entryTotalTime = timelineData.entryTotalTimes[entryIndex]; 208 var entryTotalTime = timelineData.entryTotalTimes[entryIndex];
210 var entryEndTime = entryStartTime + entryTotalTime; 209 var entryEndTime = entryStartTime + entryTotalTime;
211 var minEntryTimeWindow = Math.min(entryTotalTime, timeRight - timeLeft); 210 var minEntryTimeWindow = Math.min(entryTotalTime, timeRight - timeLeft);
212 211
213 var y = this._levelToHeight(timelineData.entryLevels[entryIndex]); 212 var level = timelineData.entryLevels[entryIndex];
214 this.setScrollOffset(y, this._barHeight); 213 this.setScrollOffset(this._levelToOffset(level), this._levelHeight(level));
215 214
216 var minVisibleWidthPx = 30; 215 var minVisibleWidthPx = 30;
217 var futurePixelToTime = (timeRight - timeLeft) / this._offsetWidth; 216 var futurePixelToTime = (timeRight - timeLeft) / this._offsetWidth;
218 minEntryTimeWindow = Math.max(minEntryTimeWindow, futurePixelToTime * minVis ibleWidthPx); 217 minEntryTimeWindow = Math.max(minEntryTimeWindow, futurePixelToTime * minVis ibleWidthPx);
219 if (timeLeft > entryEndTime) { 218 if (timeLeft > entryEndTime) {
220 var delta = timeLeft - entryEndTime + minEntryTimeWindow; 219 var delta = timeLeft - entryEndTime + minEntryTimeWindow;
221 this._flameChartDelegate.requestWindowTimes(timeLeft - delta, timeRight - delta); 220 this._flameChartDelegate.requestWindowTimes(timeLeft - delta, timeRight - delta);
222 } else if (timeRight < entryStartTime) { 221 } else if (timeRight < entryStartTime) {
223 var delta = entryStartTime - timeRight + minEntryTimeWindow; 222 var delta = entryStartTime - timeRight + minEntryTimeWindow;
224 this._flameChartDelegate.requestWindowTimes(timeLeft + delta, timeRight + delta); 223 this._flameChartDelegate.requestWindowTimes(timeLeft + delta, timeRight + delta);
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 return -1; 454 return -1;
456 y += this.getScrollOffset(); 455 y += this.getScrollOffset();
457 var timelineData = this._timelineData(); 456 var timelineData = this._timelineData();
458 if (!timelineData) 457 if (!timelineData)
459 return -1; 458 return -1;
460 var cursorTime = this._cursorTime(x); 459 var cursorTime = this._cursorTime(x);
461 var cursorLevel = this._visibleLevelOffsets.upperBound(y) - 1; 460 var cursorLevel = this._visibleLevelOffsets.upperBound(y) - 1;
462 if (cursorLevel < 0 || !this._visibleLevels[cursorLevel]) 461 if (cursorLevel < 0 || !this._visibleLevels[cursorLevel])
463 return -1; 462 return -1;
464 var offsetFromLevel = y - this._visibleLevelOffsets[cursorLevel]; 463 var offsetFromLevel = y - this._visibleLevelOffsets[cursorLevel];
465 if (offsetFromLevel > this._barHeight) 464 if (offsetFromLevel > this._levelHeight(cursorLevel))
466 return -1; 465 return -1;
467 var entryStartTimes = timelineData.entryStartTimes; 466 var entryStartTimes = timelineData.entryStartTimes;
468 var entryTotalTimes = timelineData.entryTotalTimes; 467 var entryTotalTimes = timelineData.entryTotalTimes;
469 var entryIndexes = this._timelineLevels[cursorLevel]; 468 var entryIndexes = this._timelineLevels[cursorLevel];
470 if (!entryIndexes || !entryIndexes.length) 469 if (!entryIndexes || !entryIndexes.length)
471 return -1; 470 return -1;
472 471
473 /** 472 /**
474 * @param {number} time 473 * @param {number} time
475 * @param {number} entryIndex 474 * @param {number} entryIndex
476 * @return {number} 475 * @return {number}
477 */ 476 */
478 function comparator(time, entryIndex) { 477 function comparator(time, entryIndex) {
479 return time - entryStartTimes[entryIndex]; 478 return time - entryStartTimes[entryIndex];
480 } 479 }
481 var indexOnLevel = Math.max(entryIndexes.upperBound(cursorTime, comparator) - 1, 0); 480 var indexOnLevel = Math.max(entryIndexes.upperBound(cursorTime, comparator) - 1, 0);
482 481
483 /** 482 /**
484 * @this {PerfUI.FlameChart} 483 * @this {PerfUI.FlameChart}
485 * @param {number} entryIndex 484 * @param {number} entryIndex
486 * @return {boolean} 485 * @return {boolean}
487 */ 486 */
488 function checkEntryHit(entryIndex) { 487 function checkEntryHit(entryIndex) {
489 if (entryIndex === undefined) 488 if (entryIndex === undefined)
490 return false; 489 return false;
491 var startTime = entryStartTimes[entryIndex]; 490 var startTime = entryStartTimes[entryIndex];
492 var duration = entryTotalTimes[entryIndex]; 491 var duration = entryTotalTimes[entryIndex];
493 if (isNaN(duration)) { 492 if (isNaN(duration)) {
494 var dx = (startTime - cursorTime) / this._pixelToTime; 493 var dx = (startTime - cursorTime) / this._pixelToTime;
495 var dy = this._barHeight / 2 - offsetFromLevel; 494 var dy = this._levelHeight(cursorLevel) / 2 - offsetFromLevel;
496 return dx * dx + dy * dy < this._markerRadius * this._markerRadius; 495 return dx * dx + dy * dy < this._markerRadius * this._markerRadius;
497 } 496 }
498 var endTime = startTime + duration; 497 var endTime = startTime + duration;
499 var barThreshold = 3 * this._pixelToTime; 498 var barThreshold = 3 * this._pixelToTime;
500 return startTime - barThreshold < cursorTime && cursorTime < endTime + bar Threshold; 499 return startTime - barThreshold < cursorTime && cursorTime < endTime + bar Threshold;
501 } 500 }
502 501
503 var entryIndex = entryIndexes[indexOnLevel]; 502 var entryIndex = entryIndexes[indexOnLevel];
504 if (checkEntryHit.call(this, entryIndex)) 503 if (checkEntryHit.call(this, entryIndex))
505 return entryIndex; 504 return entryIndex;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 var timeWindowRight = this._timeWindowRight; 588 var timeWindowRight = this._timeWindowRight;
590 var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._timeTo Pixel; 589 var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._timeTo Pixel;
591 var entryTotalTimes = timelineData.entryTotalTimes; 590 var entryTotalTimes = timelineData.entryTotalTimes;
592 var entryStartTimes = timelineData.entryStartTimes; 591 var entryStartTimes = timelineData.entryStartTimes;
593 var entryLevels = timelineData.entryLevels; 592 var entryLevels = timelineData.entryLevels;
594 593
595 var titleIndices = []; 594 var titleIndices = [];
596 var markerIndices = []; 595 var markerIndices = [];
597 var textPadding = this._textPadding; 596 var textPadding = this._textPadding;
598 var minTextWidth = 2 * textPadding + UI.measureTextWidth(context, '\u2026'); 597 var minTextWidth = 2 * textPadding + UI.measureTextWidth(context, '\u2026');
599 var barHeight = this._barHeight;
600 var minVisibleBarLevel = Math.max(this._visibleLevelOffsets.upperBound(top) - 1, 0); 598 var minVisibleBarLevel = Math.max(this._visibleLevelOffsets.upperBound(top) - 1, 0);
601 599
602 /** @type {!Map<string, !Array<number>>} */ 600 /** @type {!Map<string, !Array<number>>} */
603 var colorBuckets = new Map(); 601 var colorBuckets = new Map();
604 for (var level = minVisibleBarLevel; level < this._dataProvider.maxStackDept h(); ++level) { 602 for (var level = minVisibleBarLevel; level < this._dataProvider.maxStackDept h(); ++level) {
605 if (this._levelToHeight(level) > top + height) 603 if (this._levelToOffset(level) > top + height)
606 break; 604 break;
607 if (!this._visibleLevels[level]) 605 if (!this._visibleLevels[level])
608 continue; 606 continue;
609 607
610 // Entries are ordered by start time within a level, so find the last visi ble entry. 608 // Entries are ordered by start time within a level, so find the last visi ble entry.
611 var levelIndexes = this._timelineLevels[level]; 609 var levelIndexes = this._timelineLevels[level];
612 var rightIndexOnLevel = 610 var rightIndexOnLevel =
613 levelIndexes.lowerBound(timeWindowRight, (time, entryIndex) => time - entryStartTimes[entryIndex]) - 1; 611 levelIndexes.lowerBound(timeWindowRight, (time, entryIndex) => time - entryStartTimes[entryIndex]) - 1;
614 var lastDrawOffset = Infinity; 612 var lastDrawOffset = Infinity;
615 for (var entryIndexOnLevel = rightIndexOnLevel; entryIndexOnLevel >= 0; -- entryIndexOnLevel) { 613 for (var entryIndexOnLevel = rightIndexOnLevel; entryIndexOnLevel >= 0; -- entryIndexOnLevel) {
(...skipping 25 matching lines...) Expand all
641 var color = colors[c]; 639 var color = colors[c];
642 var indexes = colorBuckets.get(color); 640 var indexes = colorBuckets.get(color);
643 context.beginPath(); 641 context.beginPath();
644 context.fillStyle = color; 642 context.fillStyle = color;
645 for (var i = 0; i < indexes.length; ++i) { 643 for (var i = 0; i < indexes.length; ++i) {
646 var entryIndex = indexes[i]; 644 var entryIndex = indexes[i];
647 var entryStartTime = entryStartTimes[entryIndex]; 645 var entryStartTime = entryStartTimes[entryIndex];
648 var barX = this._timeToPositionClipped(entryStartTime); 646 var barX = this._timeToPositionClipped(entryStartTime);
649 var duration = entryTotalTimes[entryIndex]; 647 var duration = entryTotalTimes[entryIndex];
650 var barLevel = entryLevels[entryIndex]; 648 var barLevel = entryLevels[entryIndex];
651 var barY = this._levelToHeight(barLevel); 649 var barHeight = this._levelHeight(barLevel);
650 var barY = this._levelToOffset(barLevel);
652 if (isNaN(duration)) { 651 if (isNaN(duration)) {
653 context.moveTo(barX + this._markerRadius, barY + barHeight / 2); 652 context.moveTo(barX + this._markerRadius, barY + barHeight / 2);
654 context.arc(barX, barY + barHeight / 2, this._markerRadius, 0, Math.PI * 2); 653 context.arc(barX, barY + barHeight / 2, this._markerRadius, 0, Math.PI * 2);
655 markerIndices.push(entryIndex); 654 markerIndices.push(entryIndex);
656 continue; 655 continue;
657 } 656 }
658 var barRight = this._timeToPositionClipped(entryStartTime + duration); 657 var barRight = this._timeToPositionClipped(entryStartTime + duration);
659 var barWidth = Math.max(barRight - barX, 1); 658 var barWidth = Math.max(barRight - barX, 1);
660 context.rect(barX, barY, barWidth - 0.4, barHeight - 1); 659 context.rect(barX, barY, barWidth - 0.4, barHeight - 1);
661 if (barWidth > minTextWidth || this._dataProvider.forceDecoration(entryI ndex)) 660 if (barWidth > minTextWidth || this._dataProvider.forceDecoration(entryI ndex))
662 titleIndices.push(entryIndex); 661 titleIndices.push(entryIndex);
663 } 662 }
664 context.fill(); 663 context.fill();
665 } 664 }
666 665
667 context.strokeStyle = 'rgba(0, 0, 0, 0.2)'; 666 context.strokeStyle = 'rgba(0, 0, 0, 0.2)';
668 context.beginPath(); 667 context.beginPath();
669 for (var m = 0; m < markerIndices.length; ++m) { 668 for (var m = 0; m < markerIndices.length; ++m) {
670 var entryIndex = markerIndices[m]; 669 var entryIndex = markerIndices[m];
671 var entryStartTime = entryStartTimes[entryIndex]; 670 var entryStartTime = entryStartTimes[entryIndex];
672 var barX = this._timeToPositionClipped(entryStartTime); 671 var barX = this._timeToPositionClipped(entryStartTime);
673 var barLevel = entryLevels[entryIndex]; 672 var barLevel = entryLevels[entryIndex];
674 var barY = this._levelToHeight(barLevel); 673 var y = this._levelToOffset(barLevel) + this._levelHeight(barLevel) / 2;
675 context.moveTo(barX + this._markerRadius, barY + barHeight / 2); 674 context.moveTo(barX + this._markerRadius, y);
676 context.arc(barX, barY + barHeight / 2, this._markerRadius, 0, Math.PI * 2 ); 675 context.arc(barX, y, this._markerRadius, 0, Math.PI * 2);
677 } 676 }
678 context.stroke(); 677 context.stroke();
679 678
680 context.textBaseline = 'alphabetic'; 679 context.textBaseline = 'alphabetic';
681 var textBaseHeight = this._barHeight - this._textBaseline;
682
683 for (var i = 0; i < titleIndices.length; ++i) { 680 for (var i = 0; i < titleIndices.length; ++i) {
684 var entryIndex = titleIndices[i]; 681 var entryIndex = titleIndices[i];
685 var entryStartTime = entryStartTimes[entryIndex]; 682 var entryStartTime = entryStartTimes[entryIndex];
686 var barX = this._timeToPositionClipped(entryStartTime); 683 var barX = this._timeToPositionClipped(entryStartTime);
687 var barRight = Math.min(this._timeToPositionClipped(entryStartTime + entry TotalTimes[entryIndex]), width) + 1; 684 var barRight = Math.min(this._timeToPositionClipped(entryStartTime + entry TotalTimes[entryIndex]), width) + 1;
688 var barWidth = barRight - barX; 685 var barWidth = barRight - barX;
689 var barLevel = entryLevels[entryIndex]; 686 var barLevel = entryLevels[entryIndex];
690 var barY = this._levelToHeight(barLevel); 687 var barY = this._levelToOffset(barLevel);
691 var text = this._dataProvider.entryTitle(entryIndex); 688 var text = this._dataProvider.entryTitle(entryIndex);
692 if (text && text.length) { 689 if (text && text.length) {
693 context.font = this._dataProvider.entryFont(entryIndex) || defaultFont; 690 context.font = this._dataProvider.entryFont(entryIndex) || defaultFont;
694 text = UI.trimTextMiddle(context, text, barWidth - 2 * textPadding); 691 text = UI.trimTextMiddle(context, text, barWidth - 2 * textPadding);
695 } 692 }
696 var unclippedBarX = this._timeToPosition(entryStartTime); 693 var unclippedBarX = this._timeToPosition(entryStartTime);
694 var barHeight = this._levelHeight(barLevel);
697 if (this._dataProvider.decorateEntry( 695 if (this._dataProvider.decorateEntry(
698 entryIndex, context, text, barX, barY, barWidth, barHeight, unclip pedBarX, this._timeToPixel)) 696 entryIndex, context, text, barX, barY, barWidth, barHeight, unclip pedBarX, this._timeToPixel))
699 continue; 697 continue;
700 if (!text || !text.length) 698 if (!text || !text.length)
701 continue; 699 continue;
702 context.fillStyle = this._dataProvider.textColor(entryIndex); 700 context.fillStyle = this._dataProvider.textColor(entryIndex);
703 context.fillText(text, barX + textPadding, barY + textBaseHeight); 701 context.fillText(text, barX + textPadding, barY + barHeight - this._textBa seline);
704 } 702 }
705 703
706 context.restore(); 704 context.restore();
707 705
708 this._drawGroupHeaders(width, height); 706 this._drawGroupHeaders(width, height);
709 this._drawFlowEvents(context, width, height); 707 this._drawFlowEvents(context, width, height);
710 this._drawMarkers(); 708 this._drawMarkers();
711 var headerHeight = this._rulerEnabled ? PerfUI.FlameChart.HeaderHeight : 0; 709 var headerHeight = this._rulerEnabled ? PerfUI.FlameChart.HeaderHeight : 0;
712 PerfUI.TimelineGrid.drawCanvasGrid(context, this._calculator, 3, headerHeigh t); 710 PerfUI.TimelineGrid.drawCanvasGrid(context, this._calculator, 3, headerHeigh t);
713 711
714 this._updateElementPosition(this._highlightElement, this._highlightedEntryIn dex); 712 this._updateElementPosition(this._highlightElement, this._highlightedEntryIn dex);
715 this._updateElementPosition(this._selectedElement, this._selectedEntryIndex) ; 713 this._updateElementPosition(this._selectedElement, this._selectedEntryIndex) ;
716 this._updateMarkerHighlight(); 714 this._updateMarkerHighlight();
717 } 715 }
718 716
719 /** 717 /**
720 * @param {number} width 718 * @param {number} width
721 * @param {number} height 719 * @param {number} height
722 */ 720 */
723 _drawGroupHeaders(width, height) { 721 _drawGroupHeaders(width, height) {
724 var context = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getCont ext('2d')); 722 var context = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getCont ext('2d'));
725 var top = this.getScrollOffset(); 723 var top = this.getScrollOffset();
726 var ratio = window.devicePixelRatio; 724 var ratio = window.devicePixelRatio;
727 var barHeight = this._barHeight;
728 var textBaseHeight = barHeight - this._textBaseline;
729 var groups = this._rawTimelineData.groups || []; 725 var groups = this._rawTimelineData.groups || [];
730 if (!groups.length) 726 if (!groups.length)
731 return; 727 return;
732 728
733 var groupOffsets = this._groupOffsets; 729 var groupOffsets = this._groupOffsets;
734 var lastGroupOffset = Array.prototype.peekLast.call(groupOffsets); 730 var lastGroupOffset = Array.prototype.peekLast.call(groupOffsets);
735 var colorUsage = UI.ThemeSupport.ColorUsage; 731 var colorUsage = UI.ThemeSupport.ColorUsage;
736 732
737 context.save(); 733 context.save();
738 context.scale(ratio, ratio); 734 context.scale(ratio, ratio);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 }); 774 });
779 775
780 context.save(); 776 context.save();
781 forEachGroup.call(this, (offset, index, group) => { 777 forEachGroup.call(this, (offset, index, group) => {
782 context.font = group.style.font; 778 context.font = group.style.font;
783 if (this._isGroupCollapsible(index) && !group.expanded || group.style.shar eHeaderLine) { 779 if (this._isGroupCollapsible(index) && !group.expanded || group.style.shar eHeaderLine) {
784 var width = this._labelWidthForGroup(context, group) + 2; 780 var width = this._labelWidthForGroup(context, group) + 2;
785 context.fillStyle = Common.Color.parse(group.style.backgroundColor).setA lpha(0.8).asString(null); 781 context.fillStyle = Common.Color.parse(group.style.backgroundColor).setA lpha(0.8).asString(null);
786 context.fillRect( 782 context.fillRect(
787 this._headerLeftPadding - this._headerLabelXPadding, offset + this._ headerLabelYPadding, width, 783 this._headerLeftPadding - this._headerLabelXPadding, offset + this._ headerLabelYPadding, width,
788 barHeight - 2 * this._headerLabelYPadding); 784 group.style.height - 2 * this._headerLabelYPadding);
789 } 785 }
790 context.fillStyle = group.style.color; 786 context.fillStyle = group.style.color;
791 context.fillText( 787 context.fillText(
792 group.name, Math.floor(this._expansionArrowIndent * (group.style.nesti ngLevel + 1) + this._arrowSide), 788 group.name, Math.floor(this._expansionArrowIndent * (group.style.nesti ngLevel + 1) + this._arrowSide),
793 offset + textBaseHeight); 789 offset + group.style.height - this._textBaseline);
794 }); 790 });
795 context.restore(); 791 context.restore();
796 792
797 context.fillStyle = UI.themeSupport.patchColorText('#6e6e6e', colorUsage.For eground); 793 context.fillStyle = UI.themeSupport.patchColorText('#6e6e6e', colorUsage.For eground);
798 context.beginPath(); 794 context.beginPath();
799 forEachGroup.call(this, (offset, index, group) => { 795 forEachGroup.call(this, (offset, index, group) => {
800 if (this._isGroupCollapsible(index)) { 796 if (this._isGroupCollapsible(index)) {
801 drawExpansionArrow.call( 797 drawExpansionArrow.call(
802 this, this._expansionArrowIndent * (group.style.nestingLevel + 1), 798 this, this._expansionArrowIndent * (group.style.nestingLevel + 1),
803 offset + textBaseHeight - this._arrowSide / 2, !!group.expanded); 799 offset + group.style.height - this._textBaseline - this._arrowSide / 2, !!group.expanded);
804 } 800 }
805 }); 801 });
806 context.fill(); 802 context.fill();
807 803
808 context.strokeStyle = UI.themeSupport.patchColorText('#ddd', colorUsage.Back ground); 804 context.strokeStyle = UI.themeSupport.patchColorText('#ddd', colorUsage.Back ground);
809 context.beginPath(); 805 context.beginPath();
810 context.stroke(); 806 context.stroke();
811 807
812 context.restore(); 808 context.restore();
813 809
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 /** 873 /**
878 * @param {!PerfUI.FlameChart.Group} group 874 * @param {!PerfUI.FlameChart.Group} group
879 * @param {number} y 875 * @param {number} y
880 * @param {number} endLevel 876 * @param {number} endLevel
881 */ 877 */
882 _drawCollapsedOverviewForGroup(group, y, endLevel) { 878 _drawCollapsedOverviewForGroup(group, y, endLevel) {
883 var range = new Common.SegmentedRange(mergeCallback); 879 var range = new Common.SegmentedRange(mergeCallback);
884 var timeWindowRight = this._timeWindowRight; 880 var timeWindowRight = this._timeWindowRight;
885 var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._timeTo Pixel; 881 var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._timeTo Pixel;
886 var context = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getCont ext('2d')); 882 var context = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getCont ext('2d'));
887 var barHeight = this._barHeight - 1; 883 var barHeight = group.style.height;
888 var entryStartTimes = this._rawTimelineData.entryStartTimes; 884 var entryStartTimes = this._rawTimelineData.entryStartTimes;
889 var entryTotalTimes = this._rawTimelineData.entryTotalTimes; 885 var entryTotalTimes = this._rawTimelineData.entryTotalTimes;
890 886
891 for (var level = group.startLevel; level < endLevel; ++level) { 887 for (var level = group.startLevel; level < endLevel; ++level) {
892 var levelIndexes = this._timelineLevels[level]; 888 var levelIndexes = this._timelineLevels[level];
893 var rightIndexOnLevel = 889 var rightIndexOnLevel =
894 levelIndexes.lowerBound(timeWindowRight, (time, entryIndex) => time - entryStartTimes[entryIndex]) - 1; 890 levelIndexes.lowerBound(timeWindowRight, (time, entryIndex) => time - entryStartTimes[entryIndex]) - 1;
895 var lastDrawOffset = Infinity; 891 var lastDrawOffset = Infinity;
896 892
897 for (var entryIndexOnLevel = rightIndexOnLevel; entryIndexOnLevel >= 0; -- entryIndexOnLevel) { 893 for (var entryIndexOnLevel = rightIndexOnLevel; entryIndexOnLevel >= 0; -- entryIndexOnLevel) {
898 var entryIndex = levelIndexes[entryIndexOnLevel]; 894 var entryIndex = levelIndexes[entryIndexOnLevel];
899 var entryStartTime = entryStartTimes[entryIndex]; 895 var entryStartTime = entryStartTimes[entryIndex];
900 var barX = this._timeToPositionClipped(entryStartTime); 896 var barX = this._timeToPositionClipped(entryStartTime);
901 var entryEndTime = entryStartTime + entryTotalTimes[entryIndex]; 897 var entryEndTime = entryStartTime + entryTotalTimes[entryIndex];
902 if (isNaN(entryEndTime) || barX >= lastDrawOffset) 898 if (isNaN(entryEndTime) || barX >= lastDrawOffset)
903 continue; 899 continue;
904 if (entryEndTime <= timeWindowLeft) 900 if (entryEndTime <= timeWindowLeft)
905 break; 901 break;
906 lastDrawOffset = barX; 902 lastDrawOffset = barX;
907 var color = this._dataProvider.entryColor(entryIndex); 903 var color = this._dataProvider.entryColor(entryIndex);
908 var endBarX = this._timeToPositionClipped(entryEndTime); 904 var endBarX = this._timeToPositionClipped(entryEndTime);
909 if (group.style.useDecoratorsForOverview && this._dataProvider.forceDeco ration(entryIndex)) { 905 if (group.style.useDecoratorsForOverview && this._dataProvider.forceDeco ration(entryIndex)) {
910 var unclippedBarX = this._timeToPosition(entryStartTime); 906 var unclippedBarX = this._timeToPosition(entryStartTime);
911 var barWidth = endBarX - barX; 907 var barWidth = endBarX - barX;
912 context.beginPath(); 908 context.beginPath();
913 context.fillStyle = color; 909 context.fillStyle = color;
914 context.fillRect(barX, y, barWidth, barHeight); 910 context.fillRect(barX, y, barWidth, barHeight - 1);
915 this._dataProvider.decorateEntry( 911 this._dataProvider.decorateEntry(
916 entryIndex, context, '', barX, y, barWidth, this._barHeight, uncli ppedBarX, this._timeToPixel); 912 entryIndex, context, '', barX, y, barWidth, barHeight, unclippedBa rX, this._timeToPixel);
917 continue; 913 continue;
918 } 914 }
919 range.append(new Common.Segment(barX, endBarX, color)); 915 range.append(new Common.Segment(barX, endBarX, color));
920 } 916 }
921 } 917 }
922 918
923 var segments = range.segments().slice().sort((a, b) => a.data.localeCompare( b.data)); 919 var segments = range.segments().slice().sort((a, b) => a.data.localeCompare( b.data));
924 var lastColor; 920 var lastColor;
925 context.beginPath(); 921 context.beginPath();
926 for (var i = 0; i < segments.length; ++i) { 922 for (var i = 0; i < segments.length; ++i) {
927 var segment = segments[i]; 923 var segment = segments[i];
928 if (lastColor !== segments[i].data) { 924 if (lastColor !== segments[i].data) {
929 context.fill(); 925 context.fill();
930 context.beginPath(); 926 context.beginPath();
931 lastColor = segments[i].data; 927 lastColor = segments[i].data;
932 context.fillStyle = lastColor; 928 context.fillStyle = lastColor;
933 } 929 }
934 context.rect(segment.begin, y, segment.end - segment.begin, barHeight); 930 context.rect(segment.begin, y, segment.end - segment.begin, barHeight - 1) ;
935 } 931 }
936 context.fill(); 932 context.fill();
937 933
938 /** 934 /**
939 * @param {!Common.Segment} a 935 * @param {!Common.Segment} a
940 * @param {!Common.Segment} b 936 * @param {!Common.Segment} b
941 * @return {?Common.Segment} 937 * @return {?Common.Segment}
942 */ 938 */
943 function mergeCallback(a, b) { 939 function mergeCallback(a, b) {
944 return a.data === b.data && a.end + 0.4 > b.end ? a : null; 940 return a.data === b.data && a.end + 0.4 > b.end ? a : null;
(...skipping 17 matching lines...) Expand all
962 context.strokeStyle = '#7f5050'; 958 context.strokeStyle = '#7f5050';
963 var td = this._timelineData(); 959 var td = this._timelineData();
964 var endIndex = td.flowStartTimes.lowerBound(this._timeWindowRight); 960 var endIndex = td.flowStartTimes.lowerBound(this._timeWindowRight);
965 961
966 context.lineWidth = 0.5; 962 context.lineWidth = 0.5;
967 for (var i = 0; i < endIndex; ++i) { 963 for (var i = 0; i < endIndex; ++i) {
968 if (!td.flowEndTimes[i] || td.flowEndTimes[i] < this._timeWindowLeft) 964 if (!td.flowEndTimes[i] || td.flowEndTimes[i] < this._timeWindowLeft)
969 continue; 965 continue;
970 var startX = this._timeToPosition(td.flowStartTimes[i]); 966 var startX = this._timeToPosition(td.flowStartTimes[i]);
971 var endX = this._timeToPosition(td.flowEndTimes[i]); 967 var endX = this._timeToPosition(td.flowEndTimes[i]);
972 var startY = this._levelToHeight(td.flowStartLevels[i]) + this._barHeight / 2; 968 var startLevel = td.flowStartLevels[i];
973 var endY = this._levelToHeight(td.flowEndLevels[i]) + this._barHeight / 2; 969 var endLevel = td.flowEndLevels[i];
970 var startY = this._levelToOffset(startLevel) + this._levelHeight(startLeve l) / 2;
971 var endY = this._levelToOffset(endLevel) + this._levelHeight(endLevel) / 2 ;
974 972
975 973
976 var segment = Math.min((endX - startX) / 4, 40); 974 var segment = Math.min((endX - startX) / 4, 40);
977 var distanceTime = td.flowEndTimes[i] - td.flowStartTimes[i]; 975 var distanceTime = td.flowEndTimes[i] - td.flowStartTimes[i];
978 var distanceY = (endY - startY) / 10; 976 var distanceY = (endY - startY) / 10;
979 var spread = 30; 977 var spread = 30;
980 var lineY = distanceTime < 1 ? startY : spread + Math.max(0, startY + dist anceY * (i % spread)); 978 var lineY = distanceTime < 1 ? startY : spread + Math.max(0, startY + dist anceY * (i % spread));
981 979
982 var p = []; 980 var p = [];
983 p.push({x: startX, y: startY}); 981 p.push({x: startX, y: startY});
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 groups[i].expanded = expanded; 1082 groups[i].expanded = expanded;
1085 } 1083 }
1086 this._updateLevelPositions(); 1084 this._updateLevelPositions();
1087 this._updateHeight(); 1085 this._updateHeight();
1088 } 1086 }
1089 1087
1090 _updateLevelPositions() { 1088 _updateLevelPositions() {
1091 var levelCount = this._dataProvider.maxStackDepth(); 1089 var levelCount = this._dataProvider.maxStackDepth();
1092 var groups = this._rawTimelineData.groups || []; 1090 var groups = this._rawTimelineData.groups || [];
1093 this._visibleLevelOffsets = new Uint32Array(levelCount + 1); 1091 this._visibleLevelOffsets = new Uint32Array(levelCount + 1);
1092 this._visibleLevelHeights = new Uint32Array(levelCount);
1094 this._visibleLevels = new Uint16Array(levelCount); 1093 this._visibleLevels = new Uint16Array(levelCount);
1095 this._groupOffsets = new Uint32Array(groups.length + 1); 1094 this._groupOffsets = new Uint32Array(groups.length + 1);
1096 1095
1097 var groupIndex = -1; 1096 var groupIndex = -1;
1098 var currentOffset = this._rulerEnabled ? PerfUI.FlameChart.HeaderHeight : 2; 1097 var currentOffset = this._rulerEnabled ? PerfUI.FlameChart.HeaderHeight : 2;
1099 var visible = true; 1098 var visible = true;
1100 /** @type !Array<{nestingLevel: number, visible: boolean}> */ 1099 /** @type !Array<{nestingLevel: number, visible: boolean}> */
1101 var groupStack = [{nestingLevel: -1, visible: true}]; 1100 var groupStack = [{nestingLevel: -1, visible: true}];
1102 var lastGroupLevel = Math.max(levelCount, groups.length ? groups.peekLast(). startLevel + 1 : 0); 1101 var lastGroupLevel = Math.max(levelCount, groups.length ? groups.peekLast(). startLevel + 1 : 0);
1103 for (var level = 0; level < lastGroupLevel; ++level) { 1102 for (var level = 0; level < lastGroupLevel; ++level) {
(...skipping 12 matching lines...) Expand all
1116 groupStack.push({nestingLevel: style.nestingLevel, visible: visible}); 1115 groupStack.push({nestingLevel: style.nestingLevel, visible: visible});
1117 if (parentGroupIsVisible) 1116 if (parentGroupIsVisible)
1118 currentOffset += nextLevel ? 0 : style.padding; 1117 currentOffset += nextLevel ? 0 : style.padding;
1119 this._groupOffsets[groupIndex] = currentOffset; 1118 this._groupOffsets[groupIndex] = currentOffset;
1120 if (parentGroupIsVisible && !style.shareHeaderLine) 1119 if (parentGroupIsVisible && !style.shareHeaderLine)
1121 currentOffset += style.height; 1120 currentOffset += style.height;
1122 } 1121 }
1123 var isFirstOnLevel = groupIndex >= 0 && level === groups[groupIndex].start Level; 1122 var isFirstOnLevel = groupIndex >= 0 && level === groups[groupIndex].start Level;
1124 var thisLevelIsVisible = visible || isFirstOnLevel && groups[groupIndex].s tyle.useFirstLineForOverview; 1123 var thisLevelIsVisible = visible || isFirstOnLevel && groups[groupIndex].s tyle.useFirstLineForOverview;
1125 if (level < levelCount) { 1124 if (level < levelCount) {
1125 var height;
1126 if (groupIndex >= 0) {
1127 var style = groups[groupIndex].style;
1128 height = isFirstOnLevel ? style.height : (style.itemsHeight || this._b arHeight);
1129 } else {
1130 height = this._barHeight;
1131 }
1126 this._visibleLevels[level] = thisLevelIsVisible; 1132 this._visibleLevels[level] = thisLevelIsVisible;
1127 this._visibleLevelOffsets[level] = currentOffset; 1133 this._visibleLevelOffsets[level] = currentOffset;
1134 this._visibleLevelHeights[level] = height;
1128 } 1135 }
1129 if (thisLevelIsVisible || (parentGroupIsVisible && style.shareHeaderLine & & isFirstOnLevel)) 1136 if (thisLevelIsVisible || (parentGroupIsVisible && style.shareHeaderLine & & isFirstOnLevel))
1130 currentOffset += this._barHeight; 1137 currentOffset += this._visibleLevelHeights[level];
1131 } 1138 }
1132 if (groupIndex >= 0) 1139 if (groupIndex >= 0)
1133 this._groupOffsets[groupIndex + 1] = currentOffset; 1140 this._groupOffsets[groupIndex + 1] = currentOffset;
1134 this._visibleLevelOffsets[level] = currentOffset; 1141 this._visibleLevelOffsets[level] = currentOffset;
1135 } 1142 }
1136 1143
1137 /** 1144 /**
1138 * @param {number} index 1145 * @param {number} index
1139 */ 1146 */
1140 _isGroupCollapsible(index) { 1147 _isGroupCollapsible(index) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 var startTime = timelineData.entryStartTimes[entryIndex]; 1184 var startTime = timelineData.entryStartTimes[entryIndex];
1178 var endTime = startTime + (timelineData.entryTotalTimes[entryIndex] || 0); 1185 var endTime = startTime + (timelineData.entryTotalTimes[entryIndex] || 0);
1179 var barX = this._timeToPositionClipped(startTime); 1186 var barX = this._timeToPositionClipped(startTime);
1180 var barRight = this._timeToPositionClipped(endTime); 1187 var barRight = this._timeToPositionClipped(endTime);
1181 if (barRight === 0 || barX === this._offsetWidth) 1188 if (barRight === 0 || barX === this._offsetWidth)
1182 return; 1189 return;
1183 var barWidth = barRight - barX; 1190 var barWidth = barRight - barX;
1184 var barCenter = barX + barWidth / 2; 1191 var barCenter = barX + barWidth / 2;
1185 barWidth = Math.max(barWidth, elementMinWidthPx); 1192 barWidth = Math.max(barWidth, elementMinWidthPx);
1186 barX = barCenter - barWidth / 2; 1193 barX = barCenter - barWidth / 2;
1187 var barY = this._levelToHeight(timelineData.entryLevels[entryIndex]) - this. getScrollOffset(); 1194 var entryLevel = timelineData.entryLevels[entryIndex];
1195 var barY = this._levelToOffset(entryLevel) - this.getScrollOffset();
1196 var barHeight = this._levelHeight(entryLevel);
1188 var style = element.style; 1197 var style = element.style;
1189 style.left = barX + 'px'; 1198 style.left = barX + 'px';
1190 style.top = barY + 'px'; 1199 style.top = barY + 'px';
1191 style.width = barWidth + 'px'; 1200 style.width = barWidth + 'px';
1192 style.height = this._barHeight - 1 + 'px'; 1201 style.height = barHeight - 1 + 'px';
1193 this.viewportElement.appendChild(element); 1202 this.viewportElement.appendChild(element);
1194 } 1203 }
1195 1204
1196 /** 1205 /**
1197 * @param {number} time 1206 * @param {number} time
1198 * @return {number} 1207 * @return {number}
1199 */ 1208 */
1200 _timeToPositionClipped(time) { 1209 _timeToPositionClipped(time) {
1201 return Number.constrain(this._timeToPosition(time), 0, this._offsetWidth); 1210 return Number.constrain(this._timeToPosition(time), 0, this._offsetWidth);
1202 } 1211 }
1203 1212
1204 /** 1213 /**
1205 * @param {number} time 1214 * @param {number} time
1206 * @return {number} 1215 * @return {number}
1207 */ 1216 */
1208 _timeToPosition(time) { 1217 _timeToPosition(time) {
1209 return Math.floor((time - this._minimumBoundary) * this._timeToPixel) - this ._pixelWindowLeft + this._paddingLeft; 1218 return Math.floor((time - this._minimumBoundary) * this._timeToPixel) - this ._pixelWindowLeft + this._paddingLeft;
1210 } 1219 }
1211 1220
1212 /** 1221 /**
1213 * @param {number} level 1222 * @param {number} level
1214 * @return {number} 1223 * @return {number}
1215 */ 1224 */
1216 _levelToHeight(level) { 1225 _levelToOffset(level) {
1217 return this._visibleLevelOffsets[level]; 1226 return this._visibleLevelOffsets[level];
1218 } 1227 }
1219 1228
1229 /**
1230 * @param {number} level
1231 * @return {number}
1232 */
1233 _levelHeight(level) {
1234 return this._visibleLevelHeights[level];
1235 }
1236
1220 _updateBoundaries() { 1237 _updateBoundaries() {
1221 this._totalTime = this._dataProvider.totalTime(); 1238 this._totalTime = this._dataProvider.totalTime();
1222 this._minimumBoundary = this._dataProvider.minimumBoundary(); 1239 this._minimumBoundary = this._dataProvider.minimumBoundary();
1223 1240
1224 var windowWidth = 1; 1241 var windowWidth = 1;
1225 if (this._timeWindowRight !== Infinity) { 1242 if (this._timeWindowRight !== Infinity) {
1226 this._windowLeft = (this._timeWindowLeft - this._minimumBoundary) / this._ totalTime; 1243 this._windowLeft = (this._timeWindowLeft - this._minimumBoundary) / this._ totalTime;
1227 this._windowRight = (this._timeWindowRight - this._minimumBoundary) / this ._totalTime; 1244 this._windowRight = (this._timeWindowRight - this._minimumBoundary) / this ._totalTime;
1228 windowWidth = this._windowRight - this._windowLeft; 1245 windowWidth = this._windowRight - this._windowLeft;
1229 } else if (this._timeWindowLeft === Infinity) { 1246 } else if (this._timeWindowLeft === Infinity) {
1230 this._windowLeft = Infinity; 1247 this._windowLeft = Infinity;
1231 this._windowRight = Infinity; 1248 this._windowRight = Infinity;
1232 } else { 1249 } else {
1233 this._windowLeft = 0; 1250 this._windowLeft = 0;
1234 this._windowRight = 1; 1251 this._windowRight = 1;
1235 } 1252 }
1236 1253
1237 var totalPixels = Math.floor((this._offsetWidth - this._paddingLeft) / windo wWidth); 1254 var totalPixels = Math.floor((this._offsetWidth - this._paddingLeft) / windo wWidth);
1238 this._pixelWindowLeft = Math.floor(totalPixels * this._windowLeft); 1255 this._pixelWindowLeft = Math.floor(totalPixels * this._windowLeft);
1239 1256
1240 this._timeToPixel = totalPixels / this._totalTime; 1257 this._timeToPixel = totalPixels / this._totalTime;
1241 this._pixelToTime = this._totalTime / totalPixels; 1258 this._pixelToTime = this._totalTime / totalPixels;
1242 } 1259 }
1243 1260
1244 _updateHeight() { 1261 _updateHeight() {
1245 var height = this._levelToHeight(this._dataProvider.maxStackDepth()); 1262 var height = this._levelToOffset(this._dataProvider.maxStackDepth());
1246 this.setContentHeight(height); 1263 this.setContentHeight(height);
1247 } 1264 }
1248 1265
1249 /** 1266 /**
1250 * @override 1267 * @override
1251 */ 1268 */
1252 onResize() { 1269 onResize() {
1253 super.onResize(); 1270 super.onResize();
1254 this.scheduleUpdate(); 1271 this.scheduleUpdate();
1255 } 1272 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 PerfUI.FlameChart.HeaderHeight = 15; 1309 PerfUI.FlameChart.HeaderHeight = 15;
1293 1310
1294 PerfUI.FlameChart.MinimalTimeWindowMs = 0.5; 1311 PerfUI.FlameChart.MinimalTimeWindowMs = 0.5;
1295 1312
1296 /** 1313 /**
1297 * @interface 1314 * @interface
1298 */ 1315 */
1299 PerfUI.FlameChartDataProvider = function() {}; 1316 PerfUI.FlameChartDataProvider = function() {};
1300 1317
1301 /** 1318 /**
1302 * @typedef {!{name: string, startLevel: number, expanded: (boolean|undefined), style: !PerfUI.FlameChart.GroupStyle}} 1319 * @typedef {!{
1320 * name: string,
1321 * startLevel: number,
1322 * expanded: (boolean|undefined),
1323 * style: !PerfUI.FlameChart.GroupStyle
1324 * }}
1303 */ 1325 */
1304 PerfUI.FlameChart.Group; 1326 PerfUI.FlameChart.Group;
1305 1327
1306 /** 1328 /**
1307 * @typedef {!{ 1329 * @typedef {!{
1308 * height: number, 1330 * height: number,
1309 * padding: number, 1331 * padding: number,
1310 * collapsible: boolean, 1332 * collapsible: boolean,
1311 * font: string, 1333 * font: string,
1312 * color: string, 1334 * color: string,
1313 * backgroundColor: string, 1335 * backgroundColor: string,
1314 * nestingLevel: number, 1336 * nestingLevel: number,
1337 * itemsHeight: (number|undefined),
1315 * shareHeaderLine: (boolean|undefined), 1338 * shareHeaderLine: (boolean|undefined),
1316 * useFirstLineForOverview: (boolean|undefined), 1339 * useFirstLineForOverview: (boolean|undefined),
1317 * useDecoratorsForOverview: (boolean|undefined) 1340 * useDecoratorsForOverview: (boolean|undefined)
1318 * }} 1341 * }}
1319 */ 1342 */
1320 PerfUI.FlameChart.GroupStyle; 1343 PerfUI.FlameChart.GroupStyle;
1321 1344
1322 /** 1345 /**
1323 * @unrestricted 1346 * @unrestricted
1324 */ 1347 */
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1600 } 1623 }
1601 1624
1602 /** 1625 /**
1603 * @override 1626 * @override
1604 * @return {number} 1627 * @return {number}
1605 */ 1628 */
1606 boundarySpan() { 1629 boundarySpan() {
1607 return this._maximumBoundaries - this._minimumBoundaries; 1630 return this._maximumBoundaries - this._minimumBoundaries;
1608 } 1631 }
1609 }; 1632 };
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartDataProvider.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698