(self["webpackChunk_vaadin_bundles"] = self["webpackChunk_vaadin_bundles"] || []).push([["vendors-node_modules_vaadin_map_node_modules_ol_render_canvas_Executor_js"],{

/***/ "./node_modules/@vaadin/map/node_modules/ol/geom/flat/length.js":
/*!**********************************************************************!*\
  !*** ./node_modules/@vaadin/map/node_modules/ol/geom/flat/length.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "lineStringLength": () => (/* binding */ lineStringLength),
/* harmony export */   "linearRingLength": () => (/* binding */ linearRingLength)
/* harmony export */ });
/**
 * @module ol/geom/flat/length
 */

/**
 * @param {Array<number>} flatCoordinates Flat coordinates.
 * @param {number} offset Offset.
 * @param {number} end End.
 * @param {number} stride Stride.
 * @return {number} Length.
 */
function lineStringLength(flatCoordinates, offset, end, stride) {
  let x1 = flatCoordinates[offset];
  let y1 = flatCoordinates[offset + 1];
  let length = 0;
  for (let i = offset + stride; i < end; i += stride) {
    const x2 = flatCoordinates[i];
    const y2 = flatCoordinates[i + 1];
    length += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
    x1 = x2;
    y1 = y2;
  }
  return length;
}

/**
 * @param {Array<number>} flatCoordinates Flat coordinates.
 * @param {number} offset Offset.
 * @param {number} end End.
 * @param {number} stride Stride.
 * @return {number} Perimeter.
 */
function linearRingLength(flatCoordinates, offset, end, stride) {
  let perimeter = lineStringLength(flatCoordinates, offset, end, stride);
  const dx = flatCoordinates[end - stride] - flatCoordinates[offset];
  const dy = flatCoordinates[end - stride + 1] - flatCoordinates[offset + 1];
  perimeter += Math.sqrt(dx * dx + dy * dy);
  return perimeter;
}


/***/ }),

/***/ "./node_modules/@vaadin/map/node_modules/ol/geom/flat/textpath.js":
/*!************************************************************************!*\
  !*** ./node_modules/@vaadin/map/node_modules/ol/geom/flat/textpath.js ***!
  \************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "drawTextOnPath": () => (/* binding */ drawTextOnPath)
/* harmony export */ });
/* harmony import */ var _math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../math.js */ "./node_modules/@vaadin/map/node_modules/ol/math.js");
/* harmony import */ var _transform_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./transform.js */ "./node_modules/@vaadin/map/node_modules/ol/geom/flat/transform.js");
/**
 * @module ol/geom/flat/textpath
 */



/**
 * @param {Array<number>} flatCoordinates Path to put text on.
 * @param {number} offset Start offset of the `flatCoordinates`.
 * @param {number} end End offset of the `flatCoordinates`.
 * @param {number} stride Stride.
 * @param {string} text Text to place on the path.
 * @param {number} startM m along the path where the text starts.
 * @param {number} maxAngle Max angle between adjacent chars in radians.
 * @param {number} scale The product of the text scale and the device pixel ratio.
 * @param {function(string, string, Object<string, number>):number} measureAndCacheTextWidth Measure and cache text width.
 * @param {string} font The font.
 * @param {Object<string, number>} cache A cache of measured widths.
 * @param {number} rotation Rotation to apply to the flatCoordinates to determine whether text needs to be reversed.
 * @param {boolean} keepUpright Whether the text needs to be kept upright
 * @return {Array<Array<*>>|null} The result array (or null if `maxAngle` was
 * exceeded). Entries of the array are x, y, anchorX, angle, chunk.
 */
function drawTextOnPath(
  flatCoordinates,
  offset,
  end,
  stride,
  text,
  startM,
  maxAngle,
  scale,
  measureAndCacheTextWidth,
  font,
  cache,
  rotation,
  keepUpright = true,
) {
  let x2 = flatCoordinates[offset];
  let y2 = flatCoordinates[offset + 1];
  let x1 = 0;
  let y1 = 0;
  let segmentLength = 0;
  let segmentM = 0;

  function advance() {
    x1 = x2;
    y1 = y2;
    offset += stride;
    x2 = flatCoordinates[offset];
    y2 = flatCoordinates[offset + 1];
    segmentM += segmentLength;
    segmentLength = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
  }
  do {
    advance();
  } while (offset < end - stride && segmentM + segmentLength < startM);

  let interpolate =
    segmentLength === 0 ? 0 : (startM - segmentM) / segmentLength;
  const beginX = (0,_math_js__WEBPACK_IMPORTED_MODULE_0__.lerp)(x1, x2, interpolate);
  const beginY = (0,_math_js__WEBPACK_IMPORTED_MODULE_0__.lerp)(y1, y2, interpolate);

  const startOffset = offset - stride;
  const startLength = segmentM;
  const endM = startM + scale * measureAndCacheTextWidth(font, text, cache);
  while (offset < end - stride && segmentM + segmentLength < endM) {
    advance();
  }
  interpolate = segmentLength === 0 ? 0 : (endM - segmentM) / segmentLength;
  const endX = (0,_math_js__WEBPACK_IMPORTED_MODULE_0__.lerp)(x1, x2, interpolate);
  const endY = (0,_math_js__WEBPACK_IMPORTED_MODULE_0__.lerp)(y1, y2, interpolate);

  // Keep text upright if the option is selected
  let reverse = false;
  if (keepUpright) {
    if (rotation) {
      const flat = [beginX, beginY, endX, endY];
      (0,_transform_js__WEBPACK_IMPORTED_MODULE_1__.rotate)(flat, 0, 4, 2, rotation, flat, flat);
      reverse = flat[0] > flat[2];
    } else {
      reverse = beginX > endX;
    }
  }

  const PI = Math.PI;
  const result = [];
  const singleSegment = startOffset + stride === offset;

  offset = startOffset;
  segmentLength = 0;
  segmentM = startLength;
  x2 = flatCoordinates[offset];
  y2 = flatCoordinates[offset + 1];

  let previousAngle;
  // All on the same segment
  if (singleSegment) {
    advance();

    previousAngle = Math.atan2(y2 - y1, x2 - x1);
    if (reverse) {
      previousAngle += previousAngle > 0 ? -PI : PI;
    }
    const x = (endX + beginX) / 2;
    const y = (endY + beginY) / 2;
    result[0] = [x, y, (endM - startM) / 2, previousAngle, text];
    return result;
  }

  // rendering across line segments
  text = text.replace(/\n/g, ' '); // ensure rendering in single-line as all calculations below don't handle multi-lines

  for (let i = 0, ii = text.length; i < ii; ) {
    advance();
    let angle = Math.atan2(y2 - y1, x2 - x1);
    if (reverse) {
      angle += angle > 0 ? -PI : PI;
    }
    if (previousAngle !== undefined) {
      let delta = angle - previousAngle;
      delta += delta > PI ? -2 * PI : delta < -PI ? 2 * PI : 0;
      if (Math.abs(delta) > maxAngle) {
        return null;
      }
    }
    previousAngle = angle;

    const iStart = i;
    let charLength = 0;
    for (; i < ii; ++i) {
      const index = reverse ? ii - i - 1 : i;
      const len = scale * measureAndCacheTextWidth(font, text[index], cache);
      if (
        offset + stride < end &&
        segmentM + segmentLength < startM + charLength + len / 2
      ) {
        break;
      }
      charLength += len;
    }
    if (i === iStart) {
      continue;
    }
    const chars = reverse
      ? text.substring(ii - iStart, ii - i)
      : text.substring(iStart, i);
    interpolate =
      segmentLength === 0
        ? 0
        : (startM + charLength / 2 - segmentM) / segmentLength;
    const x = (0,_math_js__WEBPACK_IMPORTED_MODULE_0__.lerp)(x1, x2, interpolate);
    const y = (0,_math_js__WEBPACK_IMPORTED_MODULE_0__.lerp)(y1, y2, interpolate);
    result.push([x, y, charLength / 2, angle, chars]);
    startM += charLength;
  }
  return result;
}


/***/ }),

/***/ "./node_modules/@vaadin/map/node_modules/ol/render/canvas/Executor.js":
/*!****************************************************************************!*\
  !*** ./node_modules/@vaadin/map/node_modules/ol/render/canvas/Executor.js ***!
  \****************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _array_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../array.js */ "./node_modules/@vaadin/map/node_modules/ol/array.js");
/* harmony import */ var _extent_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../extent.js */ "./node_modules/@vaadin/map/node_modules/ol/extent.js");
/* harmony import */ var _geom_flat_length_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../geom/flat/length.js */ "./node_modules/@vaadin/map/node_modules/ol/geom/flat/length.js");
/* harmony import */ var _geom_flat_textpath_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../geom/flat/textpath.js */ "./node_modules/@vaadin/map/node_modules/ol/geom/flat/textpath.js");
/* harmony import */ var _geom_flat_transform_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geom/flat/transform.js */ "./node_modules/@vaadin/map/node_modules/ol/geom/flat/transform.js");
/* harmony import */ var _transform_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../transform.js */ "./node_modules/@vaadin/map/node_modules/ol/transform.js");
/* harmony import */ var _canvas_ZIndexContext_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../canvas/ZIndexContext.js */ "./node_modules/@vaadin/map/node_modules/ol/render/canvas/ZIndexContext.js");
/* harmony import */ var _canvas_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../canvas.js */ "./node_modules/@vaadin/map/node_modules/ol/render/canvas.js");
/* harmony import */ var _Instruction_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Instruction.js */ "./node_modules/@vaadin/map/node_modules/ol/render/canvas/Instruction.js");
/* harmony import */ var _TextBuilder_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TextBuilder.js */ "./node_modules/@vaadin/map/node_modules/ol/render/canvas/TextBuilder.js");
/**
 * @module ol/render/canvas/Executor
 */











/**
 * @typedef {import('../../structs/RBush.js').Entry<import('../../Feature.js').FeatureLike>} DeclutterEntry
 */

/**
 * @typedef {Object} ImageOrLabelDimensions
 * @property {number} drawImageX DrawImageX.
 * @property {number} drawImageY DrawImageY.
 * @property {number} drawImageW DrawImageW.
 * @property {number} drawImageH DrawImageH.
 * @property {number} originX OriginX.
 * @property {number} originY OriginY.
 * @property {Array<number>} scale Scale.
 * @property {DeclutterEntry} declutterBox DeclutterBox.
 * @property {import("../../transform.js").Transform} canvasTransform CanvasTransform.
 */

/**
 * @typedef {{0: CanvasRenderingContext2D, 1: import('../../size.js').Size, 2: import("../canvas.js").Label|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement, 3: ImageOrLabelDimensions, 4: number, 5: Array<*>, 6: Array<*>}} ReplayImageOrLabelArgs
 */

/**
 * @template T
 * @typedef {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default, import("../../style/Style.js").DeclutterMode): T} FeatureCallback
 */

/**
 * @type {import("../../extent.js").Extent}
 */
const tmpExtent = (0,_extent_js__WEBPACK_IMPORTED_MODULE_0__.createEmpty)();

/** @type {import("../../coordinate.js").Coordinate} */
const p1 = [];
/** @type {import("../../coordinate.js").Coordinate} */
const p2 = [];
/** @type {import("../../coordinate.js").Coordinate} */
const p3 = [];
/** @type {import("../../coordinate.js").Coordinate} */
const p4 = [];

/**
 * @param {ReplayImageOrLabelArgs} replayImageOrLabelArgs Arguments to replayImageOrLabel
 * @return {DeclutterEntry} Declutter rbush entry.
 */
function getDeclutterBox(replayImageOrLabelArgs) {
  return replayImageOrLabelArgs[3].declutterBox;
}

const rtlRegEx = new RegExp(
  /* eslint-disable prettier/prettier */
  '[' +
    String.fromCharCode(0x00591) + '-' + String.fromCharCode(0x008ff) +
    String.fromCharCode(0x0fb1d) + '-' + String.fromCharCode(0x0fdff) +
    String.fromCharCode(0x0fe70) + '-' + String.fromCharCode(0x0fefc) +
    String.fromCharCode(0x10800) + '-' + String.fromCharCode(0x10fff) +
    String.fromCharCode(0x1e800) + '-' + String.fromCharCode(0x1efff) +
  ']'
  /* eslint-enable prettier/prettier */
);

/**
 * @param {string} text Text.
 * @param {CanvasTextAlign} align Alignment.
 * @return {number} Text alignment.
 */
function horizontalTextAlign(text, align) {
  if (align === 'start') {
    align = rtlRegEx.test(text) ? 'right' : 'left';
  } else if (align === 'end') {
    align = rtlRegEx.test(text) ? 'left' : 'right';
  }
  return _TextBuilder_js__WEBPACK_IMPORTED_MODULE_1__.TEXT_ALIGN[align];
}

/**
 * @param {Array<string>} acc Accumulator.
 * @param {string} line Line of text.
 * @param {number} i Index
 * @return {Array<string>} Accumulator.
 */
function createTextChunks(acc, line, i) {
  if (i > 0) {
    acc.push('\n', '');
  }
  acc.push(line, '');
  return acc;
}

/**
 * Converts rich text to plain text for text along lines.
 * @param {string} result The resulting plain text.
 * @param {string} part Item of the rich text array.
 * @param {number} index Index of the item in the rich text array.
 * @return {string} The resulting plain text.
 */
function richTextToPlainText(result, part, index) {
  if (index % 2 === 0) {
    result += part;
  }
  return result;
}

class Executor {
  /**
   * @param {number} resolution Resolution.
   * @param {number} pixelRatio Pixel ratio.
   * @param {boolean} overlaps The replay can have overlapping geometries.
   * @param {import("../canvas.js").SerializableInstructions} instructions The serializable instructions.
   * @param {boolean} [deferredRendering] Enable deferred rendering.
   */
  constructor(
    resolution,
    pixelRatio,
    overlaps,
    instructions,
    deferredRendering,
  ) {
    /**
     * @protected
     * @type {boolean}
     */
    this.overlaps = overlaps;

    /**
     * @protected
     * @type {number}
     */
    this.pixelRatio = pixelRatio;

    /**
     * @protected
     * @const
     * @type {number}
     */
    this.resolution = resolution;

    /**
     * @private
     * @type {number}
     */
    this.alignAndScaleFill_;

    /**
     * @protected
     * @type {Array<*>}
     */
    this.instructions = instructions.instructions;

    /**
     * @protected
     * @type {Array<number>}
     */
    this.coordinates = instructions.coordinates;

    /**
     * @private
     * @type {!Object<number,import("../../coordinate.js").Coordinate|Array<import("../../coordinate.js").Coordinate>|Array<Array<import("../../coordinate.js").Coordinate>>>}
     */
    this.coordinateCache_ = {};

    /**
     * @private
     * @type {!import("../../transform.js").Transform}
     */
    this.renderedTransform_ = (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.create)();

    /**
     * @protected
     * @type {Array<*>}
     */
    this.hitDetectionInstructions = instructions.hitDetectionInstructions;

    /**
     * @private
     * @type {Array<number>}
     */
    this.pixelCoordinates_ = null;

    /**
     * @private
     * @type {number}
     */
    this.viewRotation_ = 0;

    /**
     * @type {!Object<string, import("../canvas.js").FillState>}
     */
    this.fillStates = instructions.fillStates || {};

    /**
     * @type {!Object<string, import("../canvas.js").StrokeState>}
     */
    this.strokeStates = instructions.strokeStates || {};

    /**
     * @type {!Object<string, import("../canvas.js").TextState>}
     */
    this.textStates = instructions.textStates || {};

    /**
     * @private
     * @type {Object<string, Object<string, number>>}
     */
    this.widths_ = {};

    /**
     * @private
     * @type {Object<string, import("../canvas.js").Label>}
     */
    this.labels_ = {};

    /**
     * @private
     * @type {import("../canvas/ZIndexContext.js").default}
     */
    this.zIndexContext_ = deferredRendering ? new _canvas_ZIndexContext_js__WEBPACK_IMPORTED_MODULE_3__["default"]() : null;
  }

  /**
   * @return {ZIndexContext} ZIndex context.
   */
  getZIndexContext() {
    return this.zIndexContext_;
  }

  /**
   * @param {string|Array<string>} text Text.
   * @param {string} textKey Text style key.
   * @param {string} fillKey Fill style key.
   * @param {string} strokeKey Stroke style key.
   * @return {import("../canvas.js").Label} Label.
   */
  createLabel(text, textKey, fillKey, strokeKey) {
    const key = text + textKey + fillKey + strokeKey;
    if (this.labels_[key]) {
      return this.labels_[key];
    }
    const strokeState = strokeKey ? this.strokeStates[strokeKey] : null;
    const fillState = fillKey ? this.fillStates[fillKey] : null;
    const textState = this.textStates[textKey];
    const pixelRatio = this.pixelRatio;
    const scale = [
      textState.scale[0] * pixelRatio,
      textState.scale[1] * pixelRatio,
    ];
    const align = textState.justify
      ? _TextBuilder_js__WEBPACK_IMPORTED_MODULE_1__.TEXT_ALIGN[textState.justify]
      : horizontalTextAlign(
          Array.isArray(text) ? text[0] : text,
          textState.textAlign || _canvas_js__WEBPACK_IMPORTED_MODULE_4__.defaultTextAlign,
        );
    const strokeWidth =
      strokeKey && strokeState.lineWidth ? strokeState.lineWidth : 0;

    const chunks = Array.isArray(text)
      ? text
      : String(text).split('\n').reduce(createTextChunks, []);

    const {width, height, widths, heights, lineWidths} = (0,_canvas_js__WEBPACK_IMPORTED_MODULE_4__.getTextDimensions)(
      textState,
      chunks,
    );
    const renderWidth = width + strokeWidth;
    const contextInstructions = [];
    // make canvas 2 pixels wider to account for italic text width measurement errors
    const w = (renderWidth + 2) * scale[0];
    const h = (height + strokeWidth) * scale[1];
    /** @type {import("../canvas.js").Label} */
    const label = {
      width: w < 0 ? Math.floor(w) : Math.ceil(w),
      height: h < 0 ? Math.floor(h) : Math.ceil(h),
      contextInstructions: contextInstructions,
    };
    if (scale[0] != 1 || scale[1] != 1) {
      contextInstructions.push('scale', scale);
    }
    if (strokeKey) {
      contextInstructions.push('strokeStyle', strokeState.strokeStyle);
      contextInstructions.push('lineWidth', strokeWidth);
      contextInstructions.push('lineCap', strokeState.lineCap);
      contextInstructions.push('lineJoin', strokeState.lineJoin);
      contextInstructions.push('miterLimit', strokeState.miterLimit);
      contextInstructions.push('setLineDash', [strokeState.lineDash]);
      contextInstructions.push('lineDashOffset', strokeState.lineDashOffset);
    }
    if (fillKey) {
      contextInstructions.push('fillStyle', fillState.fillStyle);
    }
    contextInstructions.push('textBaseline', 'middle');
    contextInstructions.push('textAlign', 'center');
    const leftRight = 0.5 - align;
    let x = align * renderWidth + leftRight * strokeWidth;
    const strokeInstructions = [];
    const fillInstructions = [];
    let lineHeight = 0;
    let lineOffset = 0;
    let widthHeightIndex = 0;
    let lineWidthIndex = 0;
    let previousFont;
    for (let i = 0, ii = chunks.length; i < ii; i += 2) {
      const text = chunks[i];
      if (text === '\n') {
        lineOffset += lineHeight;
        lineHeight = 0;
        x = align * renderWidth + leftRight * strokeWidth;
        ++lineWidthIndex;
        continue;
      }
      const font = chunks[i + 1] || textState.font;
      if (font !== previousFont) {
        if (strokeKey) {
          strokeInstructions.push('font', font);
        }
        if (fillKey) {
          fillInstructions.push('font', font);
        }
        previousFont = font;
      }
      lineHeight = Math.max(lineHeight, heights[widthHeightIndex]);
      const fillStrokeArgs = [
        text,
        x +
          leftRight * widths[widthHeightIndex] +
          align * (widths[widthHeightIndex] - lineWidths[lineWidthIndex]),
        0.5 * (strokeWidth + lineHeight) + lineOffset,
      ];
      x += widths[widthHeightIndex];
      if (strokeKey) {
        strokeInstructions.push('strokeText', fillStrokeArgs);
      }
      if (fillKey) {
        fillInstructions.push('fillText', fillStrokeArgs);
      }
      ++widthHeightIndex;
    }
    Array.prototype.push.apply(contextInstructions, strokeInstructions);
    Array.prototype.push.apply(contextInstructions, fillInstructions);
    this.labels_[key] = label;
    return label;
  }

  /**
   * @param {CanvasRenderingContext2D} context Context.
   * @param {import("../../coordinate.js").Coordinate} p1 1st point of the background box.
   * @param {import("../../coordinate.js").Coordinate} p2 2nd point of the background box.
   * @param {import("../../coordinate.js").Coordinate} p3 3rd point of the background box.
   * @param {import("../../coordinate.js").Coordinate} p4 4th point of the background box.
   * @param {Array<*>} fillInstruction Fill instruction.
   * @param {Array<*>} strokeInstruction Stroke instruction.
   */
  replayTextBackground_(
    context,
    p1,
    p2,
    p3,
    p4,
    fillInstruction,
    strokeInstruction,
  ) {
    context.beginPath();
    context.moveTo.apply(context, p1);
    context.lineTo.apply(context, p2);
    context.lineTo.apply(context, p3);
    context.lineTo.apply(context, p4);
    context.lineTo.apply(context, p1);
    if (fillInstruction) {
      this.alignAndScaleFill_ = /** @type {number} */ (fillInstruction[2]);
      context.fillStyle = /** @type {string} */ (fillInstruction[1]);
      this.fill_(context);
    }
    if (strokeInstruction) {
      this.setStrokeStyle_(
        context,
        /** @type {Array<*>} */ (strokeInstruction),
      );
      context.stroke();
    }
  }

  /**
   * @private
   * @param {number} sheetWidth Width of the sprite sheet.
   * @param {number} sheetHeight Height of the sprite sheet.
   * @param {number} centerX X.
   * @param {number} centerY Y.
   * @param {number} width Width.
   * @param {number} height Height.
   * @param {number} anchorX Anchor X.
   * @param {number} anchorY Anchor Y.
   * @param {number} originX Origin X.
   * @param {number} originY Origin Y.
   * @param {number} rotation Rotation.
   * @param {import("../../size.js").Size} scale Scale.
   * @param {boolean} snapToPixel Snap to pixel.
   * @param {Array<number>} padding Padding.
   * @param {boolean} fillStroke Background fill or stroke.
   * @param {import("../../Feature.js").FeatureLike} feature Feature.
   * @return {ImageOrLabelDimensions} Dimensions for positioning and decluttering the image or label.
   */
  calculateImageOrLabelDimensions_(
    sheetWidth,
    sheetHeight,
    centerX,
    centerY,
    width,
    height,
    anchorX,
    anchorY,
    originX,
    originY,
    rotation,
    scale,
    snapToPixel,
    padding,
    fillStroke,
    feature,
  ) {
    anchorX *= scale[0];
    anchorY *= scale[1];
    let x = centerX - anchorX;
    let y = centerY - anchorY;

    const w = width + originX > sheetWidth ? sheetWidth - originX : width;
    const h = height + originY > sheetHeight ? sheetHeight - originY : height;
    const boxW = padding[3] + w * scale[0] + padding[1];
    const boxH = padding[0] + h * scale[1] + padding[2];
    const boxX = x - padding[3];
    const boxY = y - padding[0];

    if (fillStroke || rotation !== 0) {
      p1[0] = boxX;
      p4[0] = boxX;
      p1[1] = boxY;
      p2[1] = boxY;
      p2[0] = boxX + boxW;
      p3[0] = p2[0];
      p3[1] = boxY + boxH;
      p4[1] = p3[1];
    }

    let transform;
    if (rotation !== 0) {
      transform = (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.compose)(
        (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.create)(),
        centerX,
        centerY,
        1,
        1,
        rotation,
        -centerX,
        -centerY,
      );

      (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.apply)(transform, p1);
      (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.apply)(transform, p2);
      (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.apply)(transform, p3);
      (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.apply)(transform, p4);
      (0,_extent_js__WEBPACK_IMPORTED_MODULE_0__.createOrUpdate)(
        Math.min(p1[0], p2[0], p3[0], p4[0]),
        Math.min(p1[1], p2[1], p3[1], p4[1]),
        Math.max(p1[0], p2[0], p3[0], p4[0]),
        Math.max(p1[1], p2[1], p3[1], p4[1]),
        tmpExtent,
      );
    } else {
      (0,_extent_js__WEBPACK_IMPORTED_MODULE_0__.createOrUpdate)(
        Math.min(boxX, boxX + boxW),
        Math.min(boxY, boxY + boxH),
        Math.max(boxX, boxX + boxW),
        Math.max(boxY, boxY + boxH),
        tmpExtent,
      );
    }
    if (snapToPixel) {
      x = Math.round(x);
      y = Math.round(y);
    }
    return {
      drawImageX: x,
      drawImageY: y,
      drawImageW: w,
      drawImageH: h,
      originX: originX,
      originY: originY,
      declutterBox: {
        minX: tmpExtent[0],
        minY: tmpExtent[1],
        maxX: tmpExtent[2],
        maxY: tmpExtent[3],
        value: feature,
      },
      canvasTransform: transform,
      scale: scale,
    };
  }

  /**
   * @private
   * @param {CanvasRenderingContext2D} context Context.
   * @param {import('../../size.js').Size} scaledCanvasSize Scaled canvas size.
   * @param {import("../canvas.js").Label|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} imageOrLabel Image.
   * @param {ImageOrLabelDimensions} dimensions Dimensions.
   * @param {number} opacity Opacity.
   * @param {Array<*>} fillInstruction Fill instruction.
   * @param {Array<*>} strokeInstruction Stroke instruction.
   * @return {boolean} The image or label was rendered.
   */
  replayImageOrLabel_(
    context,
    scaledCanvasSize,
    imageOrLabel,
    dimensions,
    opacity,
    fillInstruction,
    strokeInstruction,
  ) {
    const fillStroke = !!(fillInstruction || strokeInstruction);

    const box = dimensions.declutterBox;
    const strokePadding = strokeInstruction
      ? (strokeInstruction[2] * dimensions.scale[0]) / 2
      : 0;
    const intersects =
      box.minX - strokePadding <= scaledCanvasSize[0] &&
      box.maxX + strokePadding >= 0 &&
      box.minY - strokePadding <= scaledCanvasSize[1] &&
      box.maxY + strokePadding >= 0;

    if (intersects) {
      if (fillStroke) {
        this.replayTextBackground_(
          context,
          p1,
          p2,
          p3,
          p4,
          /** @type {Array<*>} */ (fillInstruction),
          /** @type {Array<*>} */ (strokeInstruction),
        );
      }
      (0,_canvas_js__WEBPACK_IMPORTED_MODULE_4__.drawImageOrLabel)(
        context,
        dimensions.canvasTransform,
        opacity,
        imageOrLabel,
        dimensions.originX,
        dimensions.originY,
        dimensions.drawImageW,
        dimensions.drawImageH,
        dimensions.drawImageX,
        dimensions.drawImageY,
        dimensions.scale,
      );
    }
    return true;
  }

  /**
   * @private
   * @param {CanvasRenderingContext2D} context Context.
   */
  fill_(context) {
    const alignAndScale = this.alignAndScaleFill_;
    if (alignAndScale) {
      const origin = (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.apply)(this.renderedTransform_, [0, 0]);
      const repeatSize = 512 * this.pixelRatio;
      context.save();
      context.translate(origin[0] % repeatSize, origin[1] % repeatSize);
      if (alignAndScale !== 1) {
        context.scale(alignAndScale, alignAndScale);
      }
      context.rotate(this.viewRotation_);
    }
    context.fill();
    if (alignAndScale) {
      context.restore();
    }
  }

  /**
   * @private
   * @param {CanvasRenderingContext2D} context Context.
   * @param {Array<*>} instruction Instruction.
   */
  setStrokeStyle_(context, instruction) {
    context.strokeStyle =
      /** @type {import("../../colorlike.js").ColorLike} */ (instruction[1]);
    if (!instruction[1]) {
      return;
    }
    context.lineWidth = /** @type {number} */ (instruction[2]);
    context.lineCap = /** @type {CanvasLineCap} */ (instruction[3]);
    context.lineJoin = /** @type {CanvasLineJoin} */ (instruction[4]);
    context.miterLimit = /** @type {number} */ (instruction[5]);
    context.lineDashOffset = /** @type {number} */ (instruction[7]);
    context.setLineDash(/** @type {Array<number>} */ (instruction[6]));
  }

  /**
   * @private
   * @param {string|Array<string>} text The text to draw.
   * @param {string} textKey The key of the text state.
   * @param {string} strokeKey The key for the stroke state.
   * @param {string} fillKey The key for the fill state.
   * @return {{label: import("../canvas.js").Label, anchorX: number, anchorY: number}} The text image and its anchor.
   */
  drawLabelWithPointPlacement_(text, textKey, strokeKey, fillKey) {
    const textState = this.textStates[textKey];

    const label = this.createLabel(text, textKey, fillKey, strokeKey);

    const strokeState = this.strokeStates[strokeKey];
    const pixelRatio = this.pixelRatio;
    const align = horizontalTextAlign(
      Array.isArray(text) ? text[0] : text,
      textState.textAlign || _canvas_js__WEBPACK_IMPORTED_MODULE_4__.defaultTextAlign,
    );
    const baseline = _TextBuilder_js__WEBPACK_IMPORTED_MODULE_1__.TEXT_ALIGN[textState.textBaseline || _canvas_js__WEBPACK_IMPORTED_MODULE_4__.defaultTextBaseline];
    const strokeWidth =
      strokeState && strokeState.lineWidth ? strokeState.lineWidth : 0;

    // Remove the 2 pixels we added in createLabel() for the anchor
    const width = label.width / pixelRatio - 2 * textState.scale[0];
    const anchorX = align * width + 2 * (0.5 - align) * strokeWidth;
    const anchorY =
      (baseline * label.height) / pixelRatio +
      2 * (0.5 - baseline) * strokeWidth;

    return {
      label: label,
      anchorX: anchorX,
      anchorY: anchorY,
    };
  }

  /**
   * @private
   * @param {CanvasRenderingContext2D} context Context.
   * @param {import('../../size.js').Size} scaledCanvasSize Scaled canvas size
   * @param {import("../../transform.js").Transform} transform Transform.
   * @param {Array<*>} instructions Instructions array.
   * @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
   * @param {FeatureCallback<T>} [featureCallback] Feature callback.
   * @param {import("../../extent.js").Extent} [hitExtent] Only check
   *     features that intersect this extent.
   * @param {import("rbush").default<DeclutterEntry>} [declutterTree] Declutter tree.
   * @return {T|undefined} Callback result.
   * @template T
   */
  execute_(
    context,
    scaledCanvasSize,
    transform,
    instructions,
    snapToPixel,
    featureCallback,
    hitExtent,
    declutterTree,
  ) {
    const zIndexContext = this.zIndexContext_;
    /** @type {Array<number>} */
    let pixelCoordinates;
    if (this.pixelCoordinates_ && (0,_array_js__WEBPACK_IMPORTED_MODULE_5__.equals)(transform, this.renderedTransform_)) {
      pixelCoordinates = this.pixelCoordinates_;
    } else {
      if (!this.pixelCoordinates_) {
        this.pixelCoordinates_ = [];
      }
      pixelCoordinates = (0,_geom_flat_transform_js__WEBPACK_IMPORTED_MODULE_6__.transform2D)(
        this.coordinates,
        0,
        this.coordinates.length,
        2,
        transform,
        this.pixelCoordinates_,
      );
      (0,_transform_js__WEBPACK_IMPORTED_MODULE_2__.setFromArray)(this.renderedTransform_, transform);
    }
    let i = 0; // instruction index
    const ii = instructions.length; // end of instructions
    let d = 0; // data index
    let dd; // end of per-instruction data
    let anchorX,
      anchorY,
      /** @type {import('../../style/Style.js').DeclutterMode} */
      declutterMode,
      prevX,
      prevY,
      roundX,
      roundY,
      image,
      text,
      textKey,
      strokeKey,
      fillKey;
    let pendingFill = 0;
    let pendingStroke = 0;
    const coordinateCache = this.coordinateCache_;
    const viewRotation = this.viewRotation_;
    const viewRotationFromTransform =
      Math.round(Math.atan2(-transform[1], transform[0]) * 1e12) / 1e12;

    const state = /** @type {import("../../render.js").State} */ ({
      context: context,
      pixelRatio: this.pixelRatio,
      resolution: this.resolution,
      rotation: viewRotation,
    });

    // When the batch size gets too big, performance decreases. 200 is a good
    // balance between batch size and number of fill/stroke instructions.
    const batchSize =
      this.instructions != instructions || this.overlaps ? 0 : 200;
    let /** @type {import("../../Feature.js").FeatureLike} */ feature;
    let x, y, currentGeometry;
    while (i < ii) {
      const instruction = instructions[i];
      const type = /** @type {import("./Instruction.js").default} */ (
        instruction[0]
      );
      switch (type) {
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].BEGIN_GEOMETRY:
          feature = /** @type {import("../../Feature.js").FeatureLike} */ (
            instruction[1]
          );
          currentGeometry = instruction[3];
          if (!feature.getGeometry()) {
            i = /** @type {number} */ (instruction[2]);
          } else if (
            hitExtent !== undefined &&
            !(0,_extent_js__WEBPACK_IMPORTED_MODULE_0__.intersects)(hitExtent, currentGeometry.getExtent())
          ) {
            i = /** @type {number} */ (instruction[2]) + 1;
          } else {
            ++i;
          }
          if (zIndexContext) {
            zIndexContext.zIndex = instruction[4];
          }
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].BEGIN_PATH:
          if (pendingFill > batchSize) {
            this.fill_(context);
            pendingFill = 0;
          }
          if (pendingStroke > batchSize) {
            context.stroke();
            pendingStroke = 0;
          }
          if (!pendingFill && !pendingStroke) {
            context.beginPath();
            prevX = NaN;
            prevY = NaN;
          }
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].CIRCLE:
          d = /** @type {number} */ (instruction[1]);
          const x1 = pixelCoordinates[d];
          const y1 = pixelCoordinates[d + 1];
          const x2 = pixelCoordinates[d + 2];
          const y2 = pixelCoordinates[d + 3];
          const dx = x2 - x1;
          const dy = y2 - y1;
          const r = Math.sqrt(dx * dx + dy * dy);
          context.moveTo(x1 + r, y1);
          context.arc(x1, y1, r, 0, 2 * Math.PI, true);
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].CLOSE_PATH:
          context.closePath();
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].CUSTOM:
          d = /** @type {number} */ (instruction[1]);
          dd = instruction[2];
          const geometry =
            /** @type {import("../../geom/SimpleGeometry.js").default} */ (
              instruction[3]
            );
          const renderer = instruction[4];
          const fn = instruction[5];
          state.geometry = geometry;
          state.feature = feature;
          if (!(i in coordinateCache)) {
            coordinateCache[i] = [];
          }
          const coords = coordinateCache[i];
          if (fn) {
            fn(pixelCoordinates, d, dd, 2, coords);
          } else {
            coords[0] = pixelCoordinates[d];
            coords[1] = pixelCoordinates[d + 1];
            coords.length = 2;
          }
          if (zIndexContext) {
            zIndexContext.zIndex = instruction[6];
          }
          renderer(coords, state);
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].DRAW_IMAGE:
          d = /** @type {number} */ (instruction[1]);
          dd = /** @type {number} */ (instruction[2]);
          image =
            /** @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} */ (
              instruction[3]
            );

          // Remaining arguments in DRAW_IMAGE are in alphabetical order
          anchorX = /** @type {number} */ (instruction[4]);
          anchorY = /** @type {number} */ (instruction[5]);
          let height = /** @type {number} */ (instruction[6]);
          const opacity = /** @type {number} */ (instruction[7]);
          const originX = /** @type {number} */ (instruction[8]);
          const originY = /** @type {number} */ (instruction[9]);
          const rotateWithView = /** @type {boolean} */ (instruction[10]);
          let rotation = /** @type {number} */ (instruction[11]);
          const scale = /** @type {import("../../size.js").Size} */ (
            instruction[12]
          );
          let width = /** @type {number} */ (instruction[13]);
          declutterMode = instruction[14] || 'declutter';
          const declutterImageWithText =
            /** @type {{args: import("../canvas.js").DeclutterImageWithText, declutterMode: import('../../style/Style.js').DeclutterMode}} */ (
              instruction[15]
            );

          if (!image && instruction.length >= 20) {
            // create label images
            text = /** @type {string} */ (instruction[19]);
            textKey = /** @type {string} */ (instruction[20]);
            strokeKey = /** @type {string} */ (instruction[21]);
            fillKey = /** @type {string} */ (instruction[22]);
            const labelWithAnchor = this.drawLabelWithPointPlacement_(
              text,
              textKey,
              strokeKey,
              fillKey,
            );
            image = labelWithAnchor.label;
            instruction[3] = image;
            const textOffsetX = /** @type {number} */ (instruction[23]);
            anchorX = (labelWithAnchor.anchorX - textOffsetX) * this.pixelRatio;
            instruction[4] = anchorX;
            const textOffsetY = /** @type {number} */ (instruction[24]);
            anchorY = (labelWithAnchor.anchorY - textOffsetY) * this.pixelRatio;
            instruction[5] = anchorY;
            height = image.height;
            instruction[6] = height;
            width = image.width;
            instruction[13] = width;
          }

          let geometryWidths;
          if (instruction.length > 25) {
            geometryWidths = /** @type {number} */ (instruction[25]);
          }

          let padding, backgroundFillInstruction, backgroundStrokeInstruction;
          if (instruction.length > 17) {
            padding = /** @type {Array<number>} */ (instruction[16]);
            backgroundFillInstruction = /** @type {Array<*>} */ (
              instruction[17]
            );
            backgroundStrokeInstruction = /** @type {Array<*>} */ (
              instruction[18]
            );
          } else {
            padding = _canvas_js__WEBPACK_IMPORTED_MODULE_4__.defaultPadding;
            backgroundFillInstruction = null;
            backgroundStrokeInstruction = null;
          }

          if (rotateWithView && viewRotationFromTransform) {
            // Canvas is expected to be rotated to reverse view rotation.
            rotation += viewRotation;
          } else if (!rotateWithView && !viewRotationFromTransform) {
            // Canvas is not rotated, images need to be rotated back to be north-up.
            rotation -= viewRotation;
          }
          let widthIndex = 0;
          for (; d < dd; d += 2) {
            if (
              geometryWidths &&
              geometryWidths[widthIndex++] < width / this.pixelRatio
            ) {
              continue;
            }
            const dimensions = this.calculateImageOrLabelDimensions_(
              image.width,
              image.height,
              pixelCoordinates[d],
              pixelCoordinates[d + 1],
              width,
              height,
              anchorX,
              anchorY,
              originX,
              originY,
              rotation,
              scale,
              snapToPixel,
              padding,
              !!backgroundFillInstruction || !!backgroundStrokeInstruction,
              feature,
            );
            /** @type {ReplayImageOrLabelArgs} */
            const args = [
              context,
              scaledCanvasSize,
              image,
              dimensions,
              opacity,
              backgroundFillInstruction,
              backgroundStrokeInstruction,
            ];
            if (declutterTree) {
              let imageArgs, imageDeclutterMode, imageDeclutterBox;
              if (declutterImageWithText) {
                const index = dd - d;
                if (!declutterImageWithText[index]) {
                  // We now have the image for an image+text combination.
                  declutterImageWithText[index] = {args, declutterMode};
                  // Don't render anything for now, wait for the text.
                  continue;
                }
                const imageDeclutter = declutterImageWithText[index];
                imageArgs = imageDeclutter.args;
                imageDeclutterMode = imageDeclutter.declutterMode;
                delete declutterImageWithText[index];
                imageDeclutterBox = getDeclutterBox(imageArgs);
              }
              // We now have image and text for an image+text combination.
              let renderImage, renderText;
              if (
                imageArgs &&
                (imageDeclutterMode !== 'declutter' ||
                  !declutterTree.collides(imageDeclutterBox))
              ) {
                renderImage = true;
              }
              if (
                declutterMode !== 'declutter' ||
                !declutterTree.collides(dimensions.declutterBox)
              ) {
                renderText = true;
              }
              if (
                imageDeclutterMode === 'declutter' &&
                declutterMode === 'declutter'
              ) {
                const render = renderImage && renderText;
                renderImage = render;
                renderText = render;
              }
              if (renderImage) {
                if (imageDeclutterMode !== 'none') {
                  declutterTree.insert(imageDeclutterBox);
                }
                this.replayImageOrLabel_.apply(this, imageArgs);
              }
              if (renderText) {
                if (declutterMode !== 'none') {
                  declutterTree.insert(dimensions.declutterBox);
                }
                this.replayImageOrLabel_.apply(this, args);
              }
            } else {
              this.replayImageOrLabel_.apply(this, args);
            }
          }
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].DRAW_CHARS:
          const begin = /** @type {number} */ (instruction[1]);
          const end = /** @type {number} */ (instruction[2]);
          const baseline = /** @type {number} */ (instruction[3]);
          const overflow = /** @type {number} */ (instruction[4]);
          fillKey = /** @type {string} */ (instruction[5]);
          const maxAngle = /** @type {number} */ (instruction[6]);
          const measurePixelRatio = /** @type {number} */ (instruction[7]);
          const offsetY = /** @type {number} */ (instruction[8]);
          strokeKey = /** @type {string} */ (instruction[9]);
          const strokeWidth = /** @type {number} */ (instruction[10]);
          text = /** @type {string|Array<string>} */ (instruction[11]);
          if (Array.isArray(text)) {
            //FIXME Add support for rich text along lines
            text = text.reduce(richTextToPlainText, '');
          }
          textKey = /** @type {string} */ (instruction[12]);
          const pixelRatioScale = [
            /** @type {number} */ (instruction[13]),
            /** @type {number} */ (instruction[13]),
          ];
          declutterMode = instruction[14] || 'declutter';

          const textKeepUpright = /** @type {boolean} */ (instruction[15]);
          const textState = this.textStates[textKey];
          const font = textState.font;
          const textScale = [
            textState.scale[0] * measurePixelRatio,
            textState.scale[1] * measurePixelRatio,
          ];

          let cachedWidths;
          if (font in this.widths_) {
            cachedWidths = this.widths_[font];
          } else {
            cachedWidths = {};
            this.widths_[font] = cachedWidths;
          }

          const pathLength = (0,_geom_flat_length_js__WEBPACK_IMPORTED_MODULE_8__.lineStringLength)(pixelCoordinates, begin, end, 2);
          const textLength =
            Math.abs(textScale[0]) *
            (0,_canvas_js__WEBPACK_IMPORTED_MODULE_4__.measureAndCacheTextWidth)(font, text, cachedWidths);
          if (overflow || textLength <= pathLength) {
            const textAlign = this.textStates[textKey].textAlign;
            const startM =
              (pathLength - textLength) * horizontalTextAlign(text, textAlign);
            const parts = (0,_geom_flat_textpath_js__WEBPACK_IMPORTED_MODULE_9__.drawTextOnPath)(
              pixelCoordinates,
              begin,
              end,
              2,
              text,
              startM,
              maxAngle,
              Math.abs(textScale[0]),
              _canvas_js__WEBPACK_IMPORTED_MODULE_4__.measureAndCacheTextWidth,
              font,
              cachedWidths,
              viewRotationFromTransform ? 0 : this.viewRotation_,
              textKeepUpright,
            );
            drawChars: if (parts) {
              /** @type {Array<ReplayImageOrLabelArgs>} */
              const replayImageOrLabelArgs = [];
              let c, cc, chars, label, part;
              if (strokeKey) {
                for (c = 0, cc = parts.length; c < cc; ++c) {
                  part = parts[c]; // x, y, anchorX, rotation, chunk
                  chars = /** @type {string} */ (part[4]);
                  label = this.createLabel(chars, textKey, '', strokeKey);
                  anchorX =
                    /** @type {number} */ (part[2]) +
                    (textScale[0] < 0 ? -strokeWidth : strokeWidth);
                  anchorY =
                    baseline * label.height +
                    ((0.5 - baseline) * 2 * strokeWidth * textScale[1]) /
                      textScale[0] -
                    offsetY;
                  const dimensions = this.calculateImageOrLabelDimensions_(
                    label.width,
                    label.height,
                    part[0],
                    part[1],
                    label.width,
                    label.height,
                    anchorX,
                    anchorY,
                    0,
                    0,
                    part[3],
                    pixelRatioScale,
                    false,
                    _canvas_js__WEBPACK_IMPORTED_MODULE_4__.defaultPadding,
                    false,
                    feature,
                  );
                  if (
                    declutterTree &&
                    declutterMode === 'declutter' &&
                    declutterTree.collides(dimensions.declutterBox)
                  ) {
                    break drawChars;
                  }
                  replayImageOrLabelArgs.push([
                    context,
                    scaledCanvasSize,
                    label,
                    dimensions,
                    1,
                    null,
                    null,
                  ]);
                }
              }
              if (fillKey) {
                for (c = 0, cc = parts.length; c < cc; ++c) {
                  part = parts[c]; // x, y, anchorX, rotation, chunk
                  chars = /** @type {string} */ (part[4]);
                  label = this.createLabel(chars, textKey, fillKey, '');
                  anchorX = /** @type {number} */ (part[2]);
                  anchorY = baseline * label.height - offsetY;
                  const dimensions = this.calculateImageOrLabelDimensions_(
                    label.width,
                    label.height,
                    part[0],
                    part[1],
                    label.width,
                    label.height,
                    anchorX,
                    anchorY,
                    0,
                    0,
                    part[3],
                    pixelRatioScale,
                    false,
                    _canvas_js__WEBPACK_IMPORTED_MODULE_4__.defaultPadding,
                    false,
                    feature,
                  );
                  if (
                    declutterTree &&
                    declutterMode === 'declutter' &&
                    declutterTree.collides(dimensions.declutterBox)
                  ) {
                    break drawChars;
                  }
                  replayImageOrLabelArgs.push([
                    context,
                    scaledCanvasSize,
                    label,
                    dimensions,
                    1,
                    null,
                    null,
                  ]);
                }
              }
              if (declutterTree && declutterMode !== 'none') {
                declutterTree.load(replayImageOrLabelArgs.map(getDeclutterBox));
              }
              for (let i = 0, ii = replayImageOrLabelArgs.length; i < ii; ++i) {
                this.replayImageOrLabel_.apply(this, replayImageOrLabelArgs[i]);
              }
            }
          }
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].END_GEOMETRY:
          if (featureCallback !== undefined) {
            feature = /** @type {import("../../Feature.js").FeatureLike} */ (
              instruction[1]
            );
            const result = featureCallback(
              feature,
              currentGeometry,
              declutterMode,
            );
            if (result) {
              return result;
            }
          }
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].FILL:
          if (batchSize) {
            pendingFill++;
          } else {
            this.fill_(context);
          }
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].MOVE_TO_LINE_TO:
          d = /** @type {number} */ (instruction[1]);
          dd = /** @type {number} */ (instruction[2]);
          x = pixelCoordinates[d];
          y = pixelCoordinates[d + 1];
          context.moveTo(x, y);
          prevX = (x + 0.5) | 0;
          prevY = (y + 0.5) | 0;
          for (d += 2; d < dd; d += 2) {
            x = pixelCoordinates[d];
            y = pixelCoordinates[d + 1];
            roundX = (x + 0.5) | 0;
            roundY = (y + 0.5) | 0;
            if (d == dd - 2 || roundX !== prevX || roundY !== prevY) {
              context.lineTo(x, y);
              prevX = roundX;
              prevY = roundY;
            }
          }
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].SET_FILL_STYLE:
          this.alignAndScaleFill_ = instruction[2];

          if (pendingFill) {
            this.fill_(context);
            pendingFill = 0;
            if (pendingStroke) {
              context.stroke();
              pendingStroke = 0;
            }
          }

          /** @type {import("../../colorlike.js").ColorLike} */
          context.fillStyle = instruction[1];
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].SET_STROKE_STYLE:
          if (pendingStroke) {
            context.stroke();
            pendingStroke = 0;
          }
          this.setStrokeStyle_(context, /** @type {Array<*>} */ (instruction));
          ++i;
          break;
        case _Instruction_js__WEBPACK_IMPORTED_MODULE_7__["default"].STROKE:
          if (batchSize) {
            pendingStroke++;
          } else {
            context.stroke();
          }
          ++i;
          break;
        default: // consume the instruction anyway, to avoid an infinite loop
          ++i;
          break;
      }
    }
    if (pendingFill) {
      this.fill_(context);
    }
    if (pendingStroke) {
      context.stroke();
    }
    return undefined;
  }

  /**
   * @param {CanvasRenderingContext2D} context Context.
   * @param {import('../../size.js').Size} scaledCanvasSize Scaled canvas size.
   * @param {import("../../transform.js").Transform} transform Transform.
   * @param {number} viewRotation View rotation.
   * @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
   * @param {import("rbush").default<DeclutterEntry>} [declutterTree] Declutter tree.
   */
  execute(
    context,
    scaledCanvasSize,
    transform,
    viewRotation,
    snapToPixel,
    declutterTree,
  ) {
    this.viewRotation_ = viewRotation;
    this.execute_(
      context,
      scaledCanvasSize,
      transform,
      this.instructions,
      snapToPixel,
      undefined,
      undefined,
      declutterTree,
    );
  }

  /**
   * @param {CanvasRenderingContext2D} context Context.
   * @param {import("../../transform.js").Transform} transform Transform.
   * @param {number} viewRotation View rotation.
   * @param {FeatureCallback<T>} [featureCallback] Feature callback.
   * @param {import("../../extent.js").Extent} [hitExtent] Only check
   *     features that intersect this extent.
   * @return {T|undefined} Callback result.
   * @template T
   */
  executeHitDetection(
    context,
    transform,
    viewRotation,
    featureCallback,
    hitExtent,
  ) {
    this.viewRotation_ = viewRotation;
    return this.execute_(
      context,
      [context.canvas.width, context.canvas.height],
      transform,
      this.hitDetectionInstructions,
      true,
      featureCallback,
      hitExtent,
    );
  }
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Executor);


/***/ }),

/***/ "./node_modules/@vaadin/map/node_modules/ol/render/canvas/ZIndexContext.js":
/*!*********************************************************************************!*\
  !*** ./node_modules/@vaadin/map/node_modules/ol/render/canvas/ZIndexContext.js ***!
  \*********************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _dom_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../dom.js */ "./node_modules/@vaadin/map/node_modules/ol/dom.js");
/**
 * @module ol/render/canvas/ZIndexContext
 */



/** @typedef {CanvasRenderingContext2D & {globalAlpha: any}} ZIndexContextProxy */

/**
 * @extends {CanvasRenderingContext2D}
 */
class ZIndexContext {
  constructor() {
    /**
     * @private
     * @type {Array<Array<*>>}
     */
    this.instructions_ = [];
    /**
     * @type {number}
     */
    this.zIndex = 0;
    /**
     * @private
     * @type {number}
     */
    this.offset_ = 0;

    /**
     * @private
     * @type {ZIndexContextProxy}
     */
    this.context_ = /** @type {ZIndexContextProxy} */ (
      new Proxy((0,_dom_js__WEBPACK_IMPORTED_MODULE_0__.getSharedCanvasContext2D)(), {
        get: (target, property) => {
          if (
            typeof (/** @type {*} */ ((0,_dom_js__WEBPACK_IMPORTED_MODULE_0__.getSharedCanvasContext2D)())[property]) !==
            'function'
          ) {
            // we only accept calling functions on the proxy, not accessing properties
            return undefined;
          }
          this.push_(property);
          return this.pushMethodArgs_;
        },
        set: (target, property, value) => {
          this.push_(property, value);
          return true;
        },
      })
    );
  }

  /**
   * @param {...*} args Arguments to push to the instructions array.
   * @private
   */
  push_(...args) {
    const instructions = this.instructions_;
    const index = this.zIndex + this.offset_;
    if (!instructions[index]) {
      instructions[index] = [];
    }
    instructions[index].push(...args);
  }

  /**
   * @private
   * @param {...*} args Args.
   * @return {ZIndexContext} This.
   */
  pushMethodArgs_ = (...args) => {
    this.push_(args);
    return this;
  };

  /**
   * Push a function that renders to the context directly.
   * @param {function(CanvasRenderingContext2D): void} render Function.
   */
  pushFunction(render) {
    this.push_(render);
  }

  /**
   * Get a proxy for CanvasRenderingContext2D which does not support getting state
   * (e.g. `context.globalAlpha`, which will return `undefined`). To set state, if it relies on a
   * previous state (e.g. `context.globalAlpha = context.globalAlpha / 2`), set a function,
   * e.g. `context.globalAlpha = (context) => context.globalAlpha / 2`.
   * @return {ZIndexContextProxy} Context.
   */
  getContext() {
    return this.context_;
  }

  /**
   * @param {CanvasRenderingContext2D} context Context.
   */
  draw(context) {
    this.instructions_.forEach((instructionsAtIndex) => {
      for (let i = 0, ii = instructionsAtIndex.length; i < ii; ++i) {
        const property = instructionsAtIndex[i];
        if (typeof property === 'function') {
          property(context);
          continue;
        }
        const instructionAtIndex = instructionsAtIndex[++i];
        if (typeof (/** @type {*} */ (context)[property]) === 'function') {
          /** @type {*} */ (context)[property](...instructionAtIndex);
        } else {
          if (typeof instructionAtIndex === 'function') {
            /** @type {*} */ (context)[property] = instructionAtIndex(context);
            continue;
          }
          /** @type {*} */ (context)[property] = instructionAtIndex;
        }
      }
    });
  }

  clear() {
    this.instructions_.length = 0;
    this.zIndex = 0;
    this.offset_ = 0;
  }

  /**
   * Offsets the zIndex by the highest current zIndex. Useful for rendering multiple worlds or tiles, to
   * avoid conflicting context.clip() or context.save()/restore() calls.
   */
  offset() {
    this.offset_ = this.instructions_.length;
    this.zIndex = 0;
  }
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ZIndexContext);


/***/ })

}])
//# sourceMappingURL=vendors-node_modules_vaadin_map_node_modules_ol_render_canvas_Executor_js.js.map