All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.render.canvas.style.js Maven / Gradle / Ivy

The newest version!
/**
 * @module ol/render/canvas/style
 */

import Circle from '../../style/Circle.js';
import Fill from '../../style/Fill.js';
import Icon from '../../style/Icon.js';
import RegularShape from '../../style/RegularShape.js';
import Stroke from '../../style/Stroke.js';
import Style from '../../style/Style.js';
import Text from '../../style/Text.js';
import {
  BooleanType,
  ColorType,
  NumberArrayType,
  NumberType,
  StringType,
  computeGeometryType,
  newParsingContext,
} from '../../expr/expression.js';
import {NO_COLOR} from '../../color.js';
import {buildExpression, newEvaluationContext} from '../../expr/cpu.js';
import {isEmpty} from '../../obj.js';
import {toSize} from '../../size.js';

/**
 * @fileoverview This module includes functions to build styles for the canvas renderer.  Building
 * is composed of two steps: parsing and compiling.  The parsing step takes an encoded expression
 * and returns an instance of one of the expression classes.  The compiling step takes the
 * expression instance and returns a function that can be evaluated to return a literal value.  The
 * evaluator function should do as little allocation and work as possible.
 */

/**
 * @typedef {import("../../style/flat.js").FlatStyle} FlatStyle
 */

/**
 * @typedef {import("../../expr/expression.js").EncodedExpression} EncodedExpression
 */

/**
 * @typedef {import("../../expr/expression.js").ParsingContext} ParsingContext
 */

/**
 * @typedef {import("../../expr/expression.js").CallExpression} CallExpression
 */

/**
 * @typedef {import("../../expr/cpu.js").EvaluationContext} EvaluationContext
 */

/**
 * @typedef {import("../../expr/cpu.js").ExpressionEvaluator} ExpressionEvaluator
 */

/**
 * @param {EvaluationContext} context The evaluation context.
 * @return {boolean} Always true.
 */
function always(context) {
  return true;
}

/**
 * This function adapts a rule evaluator to the existing style function interface.
 * After we have deprecated the style function, we can use the compiled rules directly
 * and pass a more complete evaluation context (variables, zoom, time, etc.).
 *
 * @param {Array} rules The rules.
 * @return {import('../../style/Style.js').StyleFunction} A style function.
 */
export function rulesToStyleFunction(rules) {
  const parsingContext = newParsingContext();
  const evaluator = buildRuleSet(rules, parsingContext);
  const evaluationContext = newEvaluationContext();
  return function (feature, resolution) {
    evaluationContext.properties = feature.getPropertiesInternal();
    evaluationContext.resolution = resolution;
    if (parsingContext.featureId) {
      const id = feature.getId();
      if (id !== undefined) {
        evaluationContext.featureId = id;
      } else {
        evaluationContext.featureId = null;
      }
    }
    if (parsingContext.geometryType) {
      evaluationContext.geometryType = computeGeometryType(
        feature.getGeometry(),
      );
    }
    return evaluator(evaluationContext);
  };
}

/**
 * This function adapts a style evaluator to the existing style function interface.
 * After we have deprecated the style function, we can use the compiled rules directly
 * and pass a more complete evaluation context (variables, zoom, time, etc.).
 *
 * @param {Array} flatStyles The flat styles.
 * @return {import('../../style/Style.js').StyleFunction} A style function.
 */
export function flatStylesToStyleFunction(flatStyles) {
  const parsingContext = newParsingContext();
  const length = flatStyles.length;

  /**
   * @type {Array}
   */
  const evaluators = new Array(length);
  for (let i = 0; i < length; ++i) {
    evaluators[i] = buildStyle(flatStyles[i], parsingContext);
  }
  const evaluationContext = newEvaluationContext();

  /**
   * @type {Array