process static method

ChartProcessingResult process(
  1. List<Series> series, {
  2. int renderThreshold = defaultRenderThreshold,
  3. SamplingStrategy? samplingStrategy,
  4. int? startIndex,
  5. int? endIndex,
  6. bool? useCache,
  7. String? dataSignature,
  8. void onReport(
    1. ChartDataProcessingReport report
    )?,
})

Process all series in a chart, returning ChartStats and per-series ProcessedSeries list.

Performance fix: previously this called _extractDoubles then DataSampler.fromRaw(raw.cast<dynamic>()) which re-boxed the already extracted doubles back to dynamic. Now we use DoubleListSampler directly on List<double> and only build DataPoint objects once, for the sampled subset.

renderThreshold: max points to send to the painter per series.

Implementation

static ChartProcessingResult process(
  List<Series> series, {
  int renderThreshold = defaultRenderThreshold,
  SamplingStrategy? samplingStrategy,
  // Optional viewport culling — only process indices in [startIndex..endIndex].
  int? startIndex,
  int? endIndex,
  // `null` means auto: cache only when the dataset is large enough.
  bool? useCache,
  // Optional precomputed content hash from [ChartDataSignature].
  String? dataSignature,
  void Function(ChartDataProcessingReport report)? onReport,
}) {
  final effectiveRenderThreshold = _normalizeRenderThreshold(renderThreshold);
  final cachePolicy =
      ChartDataProcessingCachePolicySnapshot.fromCurrentConfig();
  final effectiveWindow = _normalizeWindow(
    series,
    startIndex: startIndex,
    endIndex: endIndex,
  );
  final cacheAdmissionReason = processingCacheAdmissionReason(
    series,
    startIndex: effectiveWindow.startIndex,
    endIndex: effectiveWindow.endIndex,
    useCache: useCache,
    policy: cachePolicy,
  );
  final cacheEligible = _isCacheAdmissionEligible(cacheAdmissionReason);

  if (onReport != null) {
    final output = processWithReport(
      series,
      renderThreshold: effectiveRenderThreshold,
      samplingStrategy: samplingStrategy,
      startIndex: effectiveWindow.startIndex,
      endIndex: effectiveWindow.endIndex,
      useCache: useCache,
      dataSignature: dataSignature,
    );
    onReport(output.report);
    return output.result;
  }

  if (series.isEmpty) {
    return (stats: ChartStats.empty, processed: const []);
  }

  if (cacheEligible) {
    final identity = _processingCacheIdentity(
      series,
      renderThreshold: effectiveRenderThreshold,
      samplingStrategy: samplingStrategy,
      startIndex: effectiveWindow.startIndex,
      endIndex: effectiveWindow.endIndex,
      dataSignature: dataSignature,
    );
    final cached = _processingCache.get(identity.resultKey);
    if (cached != null) {
      return cached.rehydrate(series);
    }
    final result = _processUncached(
      series,
      renderThreshold: effectiveRenderThreshold,
      samplingStrategy: samplingStrategy,
      startIndex: effectiveWindow.startIndex,
      endIndex: effectiveWindow.endIndex,
      extractionSignature: identity.seriesSignature,
      useExtractionCache: true,
    );
    _processingCache.put(
      identity.resultKey,
      result,
      maxEntries: ChartDataProcessingCacheConfig.maxEntries,
      maxBytes: ChartDataProcessingCacheConfig.maxBytes,
    );
    return result;
  }

  final extractionCacheEligible = shouldUseExtractionCache(
    series,
    useCache: useCache,
    startIndex: effectiveWindow.startIndex,
    endIndex: effectiveWindow.endIndex,
    policy: cachePolicy,
  );
  return _processUncached(
    series,
    renderThreshold: effectiveRenderThreshold,
    samplingStrategy: samplingStrategy,
    startIndex: effectiveWindow.startIndex,
    endIndex: effectiveWindow.endIndex,
    extractionSignature: extractionCacheEligible
        ? _seriesDataSignature(series, dataSignature)
        : null,
    useExtractionCache: extractionCacheEligible,
  );
}