<commit_before>/**
 * @module ol/renderer/canvas/VectorImageLayer
 */
import CanvasImageLayerRenderer from './ImageLayer.js';
import CanvasVectorLayerRenderer from './VectorLayer.js';
import EventType from '../../events/EventType.js';
import ImageCanvas from '../../ImageCanvas.js';
import ImageState from '../../ImageState.js';
import ViewHint from '../../ViewHint.js';
import {apply, compose, create} from '../../transform.js';
import {assign} from '../../obj.js';
import {getHeight, getWidth, isEmpty, scaleFromCenter} from '../../extent.js';
import {renderDeclutterItems} from '../../render.js';

/**
 * @classdesc
 * Canvas renderer for image layers.
 * @api
 */
class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
  /**
   * @param {import("../../layer/VectorImage.js").default} layer Vector image layer.
   */
  constructor(layer) {
    super(layer);

    /**
     * @private
     * @type {import("./VectorLayer.js").default}
     */
    this.vectorRenderer_ = new CanvasVectorLayerRenderer(layer);

    /**
     * @private
     * @type {number}
     */
    this.layerImageRatio_ = layer.getImageRatio();

    /**
     * @private
     * @type {import("../../transform.js").Transform}
     */
    this.coordinateToVectorPixelTransform_ = create();

    /**
     * @private
     * @type {import("../../transform.js").Transform}
     */
    this.renderedPixelToCoordinateTransform_ = null;
  }

  /**
   * Clean up.
   */
  disposeInternal() {
    this.vectorRenderer_.dispose();
    super.disposeInternal();
  }

  /**
   * Asynchronous layer level hit detection.
   * @param {import("../../pixel.js").Pixel} pixel Pixel.
   * @return {Promise<Array<import("../../Feature").default>>} Promise that resolves with an array of features.
   */
  getFeatures(pixel) {
    if (this.vectorRenderer_) {
      const vectorPixel = apply(
        this.coordinateToVectorPixelTransform_,
        apply(this.renderedPixelToCoordinateTransform_, pixel.slice())
      );
      return this.vectorRenderer_.getFeatures(vectorPixel);
    } else {
      const promise = new Promise(function (resolve, reject) {
        resolve([]);
      });
      return promise;
    }
  }

  /**
   * Perform action necessary to get the layer rendered after new fonts have loaded
   */
  handleFontsChanged() {
    this.vectorRenderer_.handleFontsChanged();
  }

  /**
   * Determine whether render should be called.
   * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
   * @return {boolean} Layer is ready to be rendered.
   */
  prepareFrame(frameState) {
    const pixelRatio = frameState.pixelRatio;
    const viewState = frameState.viewState;
    const viewResolution = viewState.resolution;

    const hints = frameState.viewHints;
    const vectorRenderer = this.vectorRenderer_;
    let renderedExtent = frameState.extent;
    if (this.layerImageRatio_ !== 1) {
      renderedExtent = renderedExtent.slice(0);
      scaleFromCenter(renderedExtent, this.layerImageRatio_);
    }
    const width = getWidth(renderedExtent) / viewResolution;
    const height = getHeight(renderedExtent) / viewResolution;

    if (
      !hints[ViewHint.ANIMATING] &&
      !hints[ViewHint.INTERACTING] &&
      !isEmpty(renderedExtent)
    ) {
      vectorRenderer.useContainer(null, null, 1);
      const context = vectorRenderer.context;
      const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign(
        {},
        frameState,
        {
          declutterItems: [],
          extent: renderedExtent,
          size: [width, height],
          viewState: /** @type {import("../../View.js").State} */ (assign(
            {},
            frameState.viewState,
            {
              rotation: 0,
            }
          )),
        }
      ));
      const image = new ImageCanvas(
        renderedExtent,
        viewResolution,
        pixelRatio,
        context.canvas,
        function (callback) {
          if (
            vectorRenderer.prepareFrame(imageFrameState) &&
            vectorRenderer.replayGroupChanged
          ) {
            vectorRenderer.renderFrame(imageFrameState, null, true);
            renderDeclutterItems(imageFrameState, null);
            callback();
          }
        }
      );

      image.addEventListener(
        EventType.CHANGE,
        function () {
          if (image.getState() === ImageState.LOADED) {
            this.image_ = image;
          }
        }.bind(this)
      );
      image.load();
    }

    if (this.image_) {
      const image = this.image_;
      const imageResolution = image.getResolution();
      const imagePixelRatio = image.getPixelRatio();
      const renderedResolution =
        (imageResolution * pixelRatio) / imagePixelRatio;
      this.renderedResolution = renderedResolution;
      this.renderedPixelToCoordinateTransform_ = frameState.pixelToCoordinateTransform.slice();
      this.coordinateToVectorPixelTransform_ = compose(
        this.coordinateToVectorPixelTransform_,<commit_msg>correct clipping of the vector rendering<commit_after>/**
 * @module ol/renderer/canvas/VectorImageLayer
 */
import CanvasImageLayerRenderer from './ImageLayer.js';
import CanvasVectorLayerRenderer from './VectorLayer.js';
import EventType from '../../events/EventType.js';
import ImageCanvas from '../../ImageCanvas.js';
import ImageState from '../../ImageState.js';
import ViewHint from '../../ViewHint.js';
import {apply, compose, create} from '../../transform.js';
import {assign} from '../../obj.js';
import {getHeight, getWidth, isEmpty, scaleFromCenter} from '../../extent.js';
import {renderDeclutterItems} from '../../render.js';

/**
 * @classdesc
 * Canvas renderer for image layers.
 * @api
 */
class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
  /**
   * @param {import("../../layer/VectorImage.js").default} layer Vector image layer.
   */
  constructor(layer) {
    super(layer);

    /**
     * @private
     * @type {import("./VectorLayer.js").default}
     */
    this.vectorRenderer_ = new CanvasVectorLayerRenderer(layer);

    /**
     * @private
     * @type {number}
     */
    this.layerImageRatio_ = layer.getImageRatio();

    /**
     * @private
     * @type {import("../../transform.js").Transform}
     */
    this.coordinateToVectorPixelTransform_ = create();

    /**
     * @private
     * @type {import("../../transform.js").Transform}
     */
    this.renderedPixelToCoordinateTransform_ = null;
  }

  /**
   * Clean up.
   */
  disposeInternal() {
    this.vectorRenderer_.dispose();
    super.disposeInternal();
  }

  /**
   * Asynchronous layer level hit detection.
   * @param {import("../../pixel.js").Pixel} pixel Pixel.
   * @return {Promise<Array<import("../../Feature").default>>} Promise that resolves with an array of features.
   */
  getFeatures(pixel) {
    if (this.vectorRenderer_) {
      const vectorPixel = apply(
        this.coordinateToVectorPixelTransform_,
        apply(this.renderedPixelToCoordinateTransform_, pixel.slice())
      );
      return this.vectorRenderer_.getFeatures(vectorPixel);
    } else {
      const promise = new Promise(function (resolve, reject) {
        resolve([]);
      });
      return promise;
    }
  }

  /**
   * Perform action necessary to get the layer rendered after new fonts have loaded
   */
  handleFontsChanged() {
    this.vectorRenderer_.handleFontsChanged();
  }

  /**
   * Determine whether render should be called.
   * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
   * @return {boolean} Layer is ready to be rendered.
   */
  prepareFrame(frameState) {
    const pixelRatio = frameState.pixelRatio;
    const viewState = frameState.viewState;
    const viewResolution = viewState.resolution;

    const hints = frameState.viewHints;
    const vectorRenderer = this.vectorRenderer_;
    let renderedExtent = frameState.extent;
    if (this.layerImageRatio_ !== 1) {
      renderedExtent = renderedExtent.slice(0);
      scaleFromCenter(renderedExtent, this.layerImageRatio_);
    }
    const width = getWidth(renderedExtent) / viewResolution;
    const height = getHeight(renderedExtent) / viewResolution;

    if (
      !hints[ViewHint.ANIMATING] &&
      !hints[ViewHint.INTERACTING] &&
      !isEmpty(renderedExtent)
    ) {
      vectorRenderer.useContainer(null, null, 1);
      const context = vectorRenderer.context;
      const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign(
        {},
        frameState,
        {
          coordinateToPixelTransform: create(),
          declutterItems: [],
          extent: renderedExtent,
          size: [width, height],
          viewState: /** @type {import("../../View.js").State} */ (assign(
            {},
            frameState.viewState,
            {
              rotation: 0,
            }
          )),
        }
      ));
      const image = new ImageCanvas(
        renderedExtent,
        viewResolution,
        pixelRatio,
        context.canvas,
        function (callback) {
          if (
            vectorRenderer.prepareFrame(imageFrameState) &&
            vectorRenderer.replayGroupChanged
          ) {
            vectorRenderer.renderFrame(imageFrameState, null);
            renderDeclutterItems(imageFrameState, null);
            callback();
          }
        }
      );

      image.addEventListener(
        EventType.CHANGE,
        function () {
          if (image.getState() === ImageState.LOADED) {
            this.image_ = image;
          }
        }.bind(this)
      );
      image.load();
    }

    if (this.image_) {
      const image = this.image_;
      const imageResolution = image.getResolution();
      const imagePixelRatio = image.getPixelRatio();
      const renderedResolution =
        (imageResolution * pixelRatio) / imagePixelRatio;
      this.renderedResolution = renderedResolution;
      this.renderedPixelToCoordinateTransform_ = frameState.pixelToCoordinateTransform.slice();
      this.coordinateToVectorPixelTransform_ = compose(
        this.coordinateToVectorPixelTransform_,
{'fraction_non_alphanumeric': 0.13227304158846193, 'fraction_numerical': 0.0007902795613948434, 'mean_word_length': 2.5067544163491515, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4615548', 'n_tokens_mistral': 2820, 'n_tokens_neox': 2763, 'n_words': 569}