• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5'use strict';
6
7/**
8 * @fileoverview Provides a mechanism for drawing massive numbers of
9 * colored rectangles into a canvas in an efficient manner, provided
10 * they are drawn left to right with fixed y and height throughout.
11 *
12 * The basic idea used here is to fuse subpixel rectangles together so that
13 * we never issue a canvas fillRect for them. It turns out Javascript can
14 * do this quite efficiently, compared to asking Canvas2D to do the same.
15 *
16 * A few extra things are done by this class in the name of speed:
17 * - Viewport culling: off-viewport rectangles are discarded.
18 *
19 * - The actual discarding operation is done in world space,
20 *   e.g. pre-transform.
21 *
22 * - Rather than expending compute cycles trying to figure out an average
23 *   color for fused rectangles from css strings, you instead draw using
24 *   palletized colors. The fused rect is the max pallete index encountered.
25 *
26 * Make sure to flush the trackRenderer before finishing drawing in order
27 * to commit any queued drawing operations.
28 */
29base.exportTo('tracing', function() {
30
31  /**
32   * Creates a fast rect renderer with a specific set of culling rules
33   * and color pallette.
34   * @param {GraphicsContext2D} ctx Canvas2D drawing context.
35   * @param {number} minRectSize Only rectangles with width < minRectSize are
36   *    considered for merging.
37   * @param {number} maxMergeDist Controls how many successive small rectangles
38   *    can be merged together before issuing a rectangle.
39   * @param {Array} pallette The color pallete for drawing. Pallette slots
40   *    should map to valid Canvas fillStyle strings.
41   *
42   * @constructor
43   */
44  function FastRectRenderer(ctx, minRectSize, maxMergeDist, pallette) {
45    this.ctx_ = ctx;
46    this.minRectSize_ = minRectSize;
47    this.maxMergeDist_ = maxMergeDist;
48    this.pallette_ = pallette;
49  }
50
51  FastRectRenderer.prototype = {
52    y_: 0,
53    h_: 0,
54    merging_: false,
55    mergeStartX_: 0,
56    mergeCurRight_: 0,
57
58    /**
59     * Changes the y position and height for subsequent fillRect
60     * calls. x and width are specifieid on the fillRect calls.
61     */
62    setYandH: function(y, h) {
63      this.flush();
64      this.y_ = y;
65      this.h_ = h;
66    },
67
68    /**
69     * Fills rectangle at the specified location, if visible. If the
70     * rectangle is subpixel, it will be merged with adjacent rectangles.
71     * The drawing operation may not take effect until flush is called.
72     * @param {number} colorId The color of this rectangle, as an index
73     *     in the renderer's color pallete.
74     */
75    fillRect: function(x, w, colorId) {
76      var r = x + w;
77      if (w < this.minRectSize_) {
78        if (r - this.mergeStartX_ > this.maxMergeDist_)
79          this.flush();
80        if (!this.merging_) {
81          this.merging_ = true;
82          this.mergeStartX_ = x;
83          this.mergeCurRight_ = r;
84          this.mergedColorId = colorId;
85        } else {
86          this.mergeCurRight_ = r;
87          this.mergedColorId = Math.max(this.mergedColorId, colorId);
88        }
89      } else {
90        if (this.merging_)
91          this.flush();
92        this.ctx_.fillStyle = this.pallette_[colorId];
93        this.ctx_.fillRect(x, this.y_, w, this.h_);
94      }
95    },
96
97    /**
98     * Commits any pending fillRect operations to the underlying graphics
99     * context.
100     */
101    flush: function() {
102      if (this.merging_) {
103        this.ctx_.fillStyle = this.pallette_[this.mergedColorId];
104        this.ctx_.fillRect(this.mergeStartX_, this.y_,
105                           this.mergeCurRight_ - this.mergeStartX_, this.h_);
106        this.merging_ = false;
107      }
108    }
109  };
110
111  return {
112    FastRectRenderer: FastRectRenderer
113  };
114
115});
116