1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 | 1×
1×
1×
1×
1×
1×
1×
1×
102×
102×
102×
1×
1×
102×
102×
102×
101×
101×
101×
5×
101×
101×
101×
101×
101×
101×
101×
101×
101×
101×
5×
102×
1×
1×
1×
1×
| goog.provide('ol.renderer.canvas.IntermediateCanvas');
goog.require('ol');
goog.require('ol.coordinate');
goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.transform');
/**
* @constructor
* @abstract
* @extends {ol.renderer.canvas.Layer}
* @param {ol.layer.Layer} layer Layer.
*/
ol.renderer.canvas.IntermediateCanvas = function(layer) {
ol.renderer.canvas.Layer.call(this, layer);
/**
* @protected
* @type {ol.Transform}
*/
this.coordinateToCanvasPixelTransform = ol.transform.create();
/**
* @private
* @type {CanvasRenderingContext2D}
*/
this.hitCanvasContext_ = null;
};
ol.inherits(ol.renderer.canvas.IntermediateCanvas, ol.renderer.canvas.Layer);
/**
* @inheritDoc
*/
ol.renderer.canvas.IntermediateCanvas.prototype.composeFrame = function(frameState, layerState, context) {
this.preCompose(context, frameState);
var image = this.getImage();
if (image) {
// clipped rendering if layer extent is set
var extent = layerState.extent;
var clipped = extent !== undefined &&
!ol.extent.containsExtent(extent, frameState.extent) &&
ol.extent.intersects(extent, frameState.extent);
if (clipped) {
this.clip(context, frameState, /** @type {ol.Extent} */ (extent));
}
var imageTransform = this.getImageTransform();
// for performance reasons, context.save / context.restore is not used
// to save and restore the transformation matrix and the opacity.
// see http://jsperf.com/context-save-restore-versus-variable
var alpha = context.globalAlpha;
context.globalAlpha = layerState.opacity;
// for performance reasons, context.setTransform is only used
// when the view is rotated. see http://jsperf.com/canvas-transform
var dx = imageTransform[4];
var dy = imageTransform[5];
var dw = image.width * imageTransform[0];
var dh = image.height * imageTransform[3];
context.drawImage(image, 0, 0, +image.width, +image.height,
Math.round(dx), Math.round(dy), Math.round(dw), Math.round(dh));
context.globalAlpha = alpha;
if (clipped) {
context.restore();
}
}
this.postCompose(context, frameState, layerState);
};
/**
* @abstract
* @return {HTMLCanvasElement|HTMLVideoElement|Image} Canvas.
*/
ol.renderer.canvas.IntermediateCanvas.prototype.getImage = function() {};
/**
* @abstract
* @return {!ol.Transform} Image transform.
*/
ol.renderer.canvas.IntermediateCanvas.prototype.getImageTransform = function() {};
/**
* @inheritDoc
*/
ol.renderer.canvas.IntermediateCanvas.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
var layer = this.getLayer();
var source = layer.getSource();
var resolution = frameState.viewState.resolution;
var rotation = frameState.viewState.rotation;
var skippedFeatureUids = frameState.skippedFeatureUids;
return source.forEachFeatureAtCoordinate(
coordinate, resolution, rotation, hitTolerance, skippedFeatureUids,
/**
* @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result.
*/
function(feature) {
return callback.call(thisArg, feature, layer);
});
};
/**
* @inheritDoc
*/
ol.renderer.canvas.IntermediateCanvas.prototype.forEachLayerAtCoordinate = function(coordinate, frameState, callback, thisArg) {
if (!this.getImage()) {
return undefined;
}
if (this.getLayer().getSource().forEachFeatureAtCoordinate !== ol.nullFunction) {
// for ImageVector sources use the original hit-detection logic,
// so that for example also transparent polygons are detected
return ol.renderer.canvas.Layer.prototype.forEachLayerAtCoordinate.apply(this, arguments);
} else {
var pixel = ol.transform.apply(this.coordinateToCanvasPixelTransform, coordinate.slice());
ol.coordinate.scale(pixel, frameState.viewState.resolution / this.renderedResolution);
if (!this.hitCanvasContext_) {
this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1);
}
this.hitCanvasContext_.clearRect(0, 0, 1, 1);
this.hitCanvasContext_.drawImage(this.getImage(), pixel[0], pixel[1], 1, 1, 0, 0, 1, 1);
var imageData = this.hitCanvasContext_.getImageData(0, 0, 1, 1).data;
if (imageData[3] > 0) {
return callback.call(thisArg, this.getLayer(), imageData);
} else {
return undefined;
}
}
};
|