parseModelColor function

LatexColor? parseModelColor(
  1. String model,
  2. String value, {
  3. LatexColor? defined(
    1. String name
    )?,
})

Parses an xcolor model specification: \color[rgb]{0.1,0.2,0.3}. Supported models: rgb (0–1), RGB (0–255), HTML (hex), gray (0–1), cmyk (0–1, converted as xcolor converts), named (a colour name, defined giving a formula's own). Of a list of models (rgb/cmyk with 1,0,0/0,1,1,0) the first is used. Returns null if the value is invalid.

Implementation

LatexColor? parseModelColor(
  String model,
  String value, {
  LatexColor? Function(String name)? defined,
}) {
  if (model.contains('/')) {
    model = model.substring(0, model.indexOf('/')).trim();
    if (value.contains('/')) value = value.substring(0, value.indexOf('/'));
  }
  if (model == 'named') return parseColor(value, defined: defined);
  final parts = value.split(',').map((s) => s.trim()).toList();
  double? unit(String s) {
    final v = double.tryParse(s);
    return v == null || v < 0 || v > 1 ? null : v;
  }

  int byte(double v) => (v * 255).round();
  switch (model) {
    case 'rgb':
      if (parts.length != 3) return null;
      final c = parts.map(unit).toList();
      if (c.contains(null)) return null;
      return LatexColor.fromARGB(0xFF, byte(c[0]!), byte(c[1]!), byte(c[2]!));
    case 'RGB':
      if (parts.length != 3) return null;
      final c = parts.map(int.tryParse).toList();
      if (c.any((v) => v == null || v < 0 || v > 255)) return null;
      return LatexColor.fromARGB(0xFF, c[0]!, c[1]!, c[2]!);
    case 'HTML':
      if (!RegExp(r'^[0-9a-fA-F]{6}$').hasMatch(value.trim())) return null;
      return LatexColor(0xFF000000 | int.parse(value.trim(), radix: 16));
    case 'gray':
      if (parts.length != 1) return null;
      final g = unit(parts[0]);
      if (g == null) return null;
      return LatexColor.fromARGB(0xFF, byte(g), byte(g), byte(g));
    case 'cmyk':
      if (parts.length != 4) return null;
      final c = parts.map(unit).toList();
      if (c.contains(null)) return null;
      // xcolor: cmyk → cmy is min(1, c + k), then rgb = 1 − cmy.
      final k = c[3]!;
      int channel(double v) => byte(1 - math.min(1, v + k));
      return LatexColor.fromARGB(
        0xFF,
        channel(c[0]!),
        channel(c[1]!),
        channel(c[2]!),
      );
  }
  return null;
}