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