preprocessSeries method

  1. @override
void preprocessSeries(
  1. List<MutableSeries<D>> seriesList
)

Pre-calculates some details for the series that will be needed later during the drawing phase.

Implementation

@override
void preprocessSeries(List<MutableSeries<D>> seriesList) {
  var stackIndex = 0;

  _hasMeasureBounds = seriesList.any((series) =>
  series.measureUpperBoundFn != null &&
      series.measureLowerBoundFn != null);

  for (var series in seriesList) {
    final colorFn = series.colorFn;
    final areaColorFn = series.areaColorFn;
    final domainFn = series.domainFn;
    final measureFn = series.measureFn;
    final strokeWidthPxFn = series.strokeWidthPxFn;

    series.dashPatternFn ??= (_) => config.dashPattern;
    final dashPatternFn = series.dashPatternFn!;

    final styleSegments = <_LineRendererElement<D>>[];
    var styleSegmentsIndex = 0;

    final usedKeys = <String>{};

    // Configure style segments for each series.
    String? previousSegmentKey;
    _LineRendererElement<D>? currentDetails;

    for (var index = 0; index < series.data.length; index++) {
      final domain = domainFn(index);
      final measure = measureFn(index);

      if (domain == null || measure == null) {
        continue;
      }

      final color = colorFn!(index);
      final areaColor = areaColorFn!(index);
      final dashPattern = dashPatternFn(index);
      final strokeWidthPx =
          strokeWidthPxFn?.call(index)?.toDouble() ?? config.strokeWidthPx;

      // Create a style key for this datum, and then compare it to the
      // previous datum.
      //
      // Compare strokeWidthPx to 2 decimals of precision. Any less and you
      // can't see any difference in the canvas anyways.
      final strokeWidthPxRounded = (strokeWidthPx * 100).round() / 100;
      var styleKey = '${series.id}__${styleSegmentsIndex}__$color'
          '__${dashPattern}__$strokeWidthPxRounded';

      if (styleKey != previousSegmentKey) {
        // If we have a repeated style segment, update the repeat index and
        // create a new key.
        // TODO: Paint repeated styles with multiple clip regions.
        if (usedKeys.isNotEmpty && usedKeys.contains(styleKey)) {
          styleSegmentsIndex++;

          styleKey = '${series.id}__${styleSegmentsIndex}__$color'
              '__${dashPattern}__$strokeWidthPxRounded';
        }

        // Make sure that the previous style segment extends to the current
        // domain value. This will ensure that the style of the line changes
        // right at the point of the datum that changes the style.
        if (currentDetails != null) {
          currentDetails.domainExtent.includePoint(domain);
        }

        // Create a new style segment.
        currentDetails = _LineRendererElement<D>(
          color: color,
          areaColor: areaColor,
          dashPattern: dashPattern,
          domainExtent: _Range<D>(domain, domain),
          strokeWidthPx: strokeWidthPx,
          styleKey: styleKey,
          roundEndCaps: config.roundEndCaps,
        );

        styleSegments.add(currentDetails);
        usedKeys.add(styleKey);

        previousSegmentKey = styleKey;
      } else {
        // Extend the range of the current segment to include the current
        // domain value.
        currentDetails!.domainExtent.includePoint(domain);
      }
    }

    series.setAttr(styleSegmentsKey, styleSegments);
    series.setAttr(lineStackIndexKey, stackIndex);

    if (config.stacked) {
      stackIndex++;
    }
  }

  if (config.includePoints) {
    _pointRenderer.preprocessSeries(seriesList);
  }

  // If we are stacking, generate new stacking measure offset functions for
  // each series. Each datum should have a measure offset consisting of the
  // sum of the measure and measure offsets of each datum with the same domain
  // value in series below it in the stack. The first series will be treated
  // as the bottom of the stack.
  if (config.stacked && seriesList.isNotEmpty) {
    var curOffsets = _createInitialOffsetMap(seriesList[0]);
    var nextOffsets = <D, num>{};

    for (var i = 0; i < seriesList.length; i++) {
      final series = seriesList[i];
      final measureOffsetFn = _createStackedMeasureOffsetFunction(
          series, curOffsets, nextOffsets);

      if (i > 0) {
        series.measureOffsetFn = measureOffsetFn;
      }

      curOffsets = nextOffsets;
      nextOffsets = <D, num>{};
    }
  }
}