# all files / ol/renderer/canvas/ intermediatecanvas.js

24.56% Statements 14/57
0% Branches 0/17
0% Functions 0/7
24.56% Lines 14/57

    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
    1481×

    1×
    1×
    1×
    1×
    1×
    1×

    1×

    1×

    1×

    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;
        }
      }
    };