• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2018 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {assertTrue} from '../base/logging';
16import {duration, Span, time} from '../base/time';
17import {
18  HighPrecisionTime,
19  HighPrecisionTimeSpan,
20} from '../common/high_precision_time';
21
22export class TimeScale {
23  private _start: HighPrecisionTime;
24  private _durationNanos: number;
25  readonly pxSpan: PxSpan;
26  private _nanosPerPx = 0;
27
28  static fromHPTimeSpan(span: Span<HighPrecisionTime>, pxSpan: PxSpan) {
29    return new TimeScale(span.start, span.duration.nanos, pxSpan);
30  }
31
32  constructor(start: HighPrecisionTime, durationNanos: number, pxSpan: PxSpan) {
33    this.pxSpan = pxSpan;
34    this._start = start;
35    this._durationNanos = durationNanos;
36    if (durationNanos <= 0 || pxSpan.delta <= 0) {
37      this._nanosPerPx = 1;
38    } else {
39      this._nanosPerPx = durationNanos / pxSpan.delta;
40    }
41  }
42
43  get timeSpan(): Span<HighPrecisionTime> {
44    const end = this._start.addNanos(this._durationNanos);
45    return new HighPrecisionTimeSpan(this._start, end);
46  }
47
48  timeToPx(ts: time): number {
49    // WARNING: Number(bigint) can be surprisingly slow. Avoid in hotpath.
50    const timeOffsetNanos = Number(ts - this._start.base) - this._start.offset;
51    return this.pxSpan.start + timeOffsetNanos / this._nanosPerPx;
52  }
53
54  hpTimeToPx(time: HighPrecisionTime): number {
55    const timeOffsetNanos = time.sub(this._start).nanos;
56    return this.pxSpan.start + timeOffsetNanos / this._nanosPerPx;
57  }
58
59  // Convert pixels to a high precision time object, which can be futher
60  // converted to other time formats.
61  pxToHpTime(px: number): HighPrecisionTime {
62    const offsetNanos = (px - this.pxSpan.start) * this._nanosPerPx;
63    return this._start.addNanos(offsetNanos);
64  }
65
66  durationToPx(dur: duration): number {
67    // WARNING: Number(bigint) can be surprisingly slow. Avoid in hotpath.
68    return Number(dur) / this._nanosPerPx;
69  }
70
71  pxDeltaToDuration(pxDelta: number): HighPrecisionTime {
72    const time = pxDelta * this._nanosPerPx;
73    return HighPrecisionTime.fromNanos(time);
74  }
75}
76
77export class PxSpan {
78  static readonly ZERO = new PxSpan(0, 0);
79
80  constructor(private _start: number, private _end: number) {
81    assertTrue(_start <= _end, 'PxSpan start > end');
82  }
83
84  get start(): number {
85    return this._start;
86  }
87
88  get end(): number {
89    return this._end;
90  }
91
92  get delta(): number {
93    return this._end - this._start;
94  }
95}
96