resolveFontFeaturesForVariant static method

({List<FontFeature> features, FontVariantCapsSynthesis synth}) resolveFontFeaturesForVariant(
  1. CSSRenderStyle renderStyle
)

Implementation

static ({List<ui.FontFeature> features, FontVariantCapsSynthesis synth}) resolveFontFeaturesForVariant(
    CSSRenderStyle renderStyle) {
  final String v = renderStyle.fontVariant;
  if (v.isEmpty || v == 'normal') {
    return (features: const <ui.FontFeature>[], synth: FontVariantCapsSynthesis.none);
  }

  if (v == 'none') {
    // Treat as disabling common/contextual/discretionary/historical ligatures.
    return (
      features: const <ui.FontFeature>[
        ui.FontFeature('liga', 0),
        ui.FontFeature('clig', 0),
        ui.FontFeature('calt', 0),
        ui.FontFeature('dlig', 0),
        ui.FontFeature('hlig', 0),
      ],
      synth: FontVariantCapsSynthesis.none
    );
  }

  final tokens = v.split(RegExp(r'\s+')).where((t) => t.isNotEmpty).toList();
  final List<ui.FontFeature> features = <ui.FontFeature>[];
  FontVariantCapsSynthesis synth = FontVariantCapsSynthesis.none;

  final bool hasAllSmallCaps = tokens.contains('all-small-caps');
  final bool hasSmallCaps = tokens.contains('small-caps');
  final bool hasAllPetiteCaps = tokens.contains('all-petite-caps');
  final bool hasPetiteCaps = tokens.contains('petite-caps');

  if (hasAllSmallCaps || hasSmallCaps) {
    final bool hasSmcp = supportsFontFeature(renderStyle, 'smcp');
    final bool hasC2sc = hasAllSmallCaps ? supportsFontFeature(renderStyle, 'c2sc') : true;
    if (hasAllSmallCaps && hasSmcp && hasC2sc) {
      features.add(const ui.FontFeature.enable('smcp'));
      features.add(const ui.FontFeature.enable('c2sc'));
    } else if (!hasAllSmallCaps && hasSmcp) {
      features.add(const ui.FontFeature.enable('smcp'));
    } else {
      synth = hasAllSmallCaps ? FontVariantCapsSynthesis.allLetters : FontVariantCapsSynthesis.lowercaseOnly;
    }
  } else if (hasAllPetiteCaps || hasPetiteCaps) {
    final bool hasPcap = supportsFontFeature(renderStyle, 'pcap');
    final bool hasC2pc = hasAllPetiteCaps ? supportsFontFeature(renderStyle, 'c2pc') : true;
    if (hasAllPetiteCaps && hasPcap && hasC2pc) {
      features.add(const ui.FontFeature.enable('pcap'));
      features.add(const ui.FontFeature.enable('c2pc'));
    } else if (!hasAllPetiteCaps && hasPcap) {
      features.add(const ui.FontFeature.enable('pcap'));
    } else {
      synth = hasAllPetiteCaps ? FontVariantCapsSynthesis.allLetters : FontVariantCapsSynthesis.lowercaseOnly;
    }
  } else if (tokens.contains('unicase')) {
    features.add(const ui.FontFeature.enable('unic'));
  } else if (tokens.contains('titling-caps')) {
    features.add(const ui.FontFeature.enable('titl'));
  }

  for (final t in tokens) {
    switch (t) {
      // Ligatures
      case 'common-ligatures':
        features.add(const ui.FontFeature.enable('liga'));
        features.add(const ui.FontFeature.enable('clig'));
        break;
      case 'no-common-ligatures':
        features.add(const ui.FontFeature('liga', 0));
        features.add(const ui.FontFeature('clig', 0));
        break;
      case 'discretionary-ligatures':
        features.add(const ui.FontFeature.enable('dlig'));
        break;
      case 'no-discretionary-ligatures':
        features.add(const ui.FontFeature('dlig', 0));
        break;
      case 'historical-ligatures':
        features.add(const ui.FontFeature.enable('hlig'));
        break;
      case 'no-historical-ligatures':
        features.add(const ui.FontFeature('hlig', 0));
        break;
      case 'contextual':
        features.add(const ui.FontFeature.enable('calt'));
        break;
      case 'no-contextual':
        features.add(const ui.FontFeature('calt', 0));
        break;
      case 'historical-forms':
        features.add(const ui.FontFeature.enable('hist'));
        break;

      // Numeric
      case 'lining-nums':
        features.add(const ui.FontFeature.enable('lnum'));
        break;
      case 'oldstyle-nums':
        features.add(const ui.FontFeature.enable('onum'));
        break;
      case 'proportional-nums':
        features.add(const ui.FontFeature.enable('pnum'));
        break;
      case 'tabular-nums':
        features.add(const ui.FontFeature.enable('tnum'));
        break;
      case 'diagonal-fractions':
        features.add(const ui.FontFeature.enable('frac'));
        break;
      case 'stacked-fractions':
        features.add(const ui.FontFeature.enable('afrc'));
        break;
      case 'slashed-zero':
        features.add(const ui.FontFeature.enable('zero'));
        break;
      case 'ordinal':
        features.add(const ui.FontFeature.enable('ordn'));
        break;

      // East Asian
      case 'jis78':
        features.add(const ui.FontFeature.enable('jp78'));
        break;
      case 'jis83':
        features.add(const ui.FontFeature.enable('jp83'));
        break;
      case 'jis90':
        features.add(const ui.FontFeature.enable('jp90'));
        break;
      case 'jis04':
        features.add(const ui.FontFeature.enable('jp04'));
        break;
      case 'simplified':
        features.add(const ui.FontFeature.enable('smpl'));
        break;
      case 'traditional':
        features.add(const ui.FontFeature.enable('trad'));
        break;
      case 'full-width':
        features.add(const ui.FontFeature.enable('fwid'));
        break;
      case 'proportional-width':
        features.add(const ui.FontFeature.enable('pwid'));
        break;
      case 'ruby':
        features.add(const ui.FontFeature.enable('ruby'));
        break;

      // Position
      case 'sub':
        features.add(const ui.FontFeature.enable('subs'));
        break;
      case 'super':
        features.add(const ui.FontFeature.enable('sups'));
        break;
      default:
        break;
    }
  }

  return (features: features, synth: synth);
}