Newer
Older
SmTIAS-Capture / lib / models / preview_region.dart
/// プレビュー表示領域を表す正規化矩形(不変クラス).
///
/// 撮影画像(フル領域)に対する正規化座標(0.0–1.0)で,
/// CameraPreview をクロップ表示する領域を表す.
/// 撮影画像の出力には影響しない(プレビュー表示のみ).
class PreviewRegion {
  /// 左端(0.0–1.0).
  final double left;

  /// 上端(0.0–1.0).
  final double top;

  /// 右端(0.0–1.0).
  final double right;

  /// 下端(0.0–1.0).
  final double bottom;

  const PreviewRegion({
    required this.left,
    required this.top,
    required this.right,
    required this.bottom,
  });

  /// クロップなし(フル領域)を表す矩形.
  ///
  /// config 読み込み失敗時のフォールバックとして使用する.
  static const PreviewRegion full = PreviewRegion(
    left: 0.0,
    top: 0.0,
    right: 1.0,
    bottom: 1.0,
  );

  /// クロップ領域の幅(正規化).
  double get width => right - left;

  /// クロップ領域の高さ(正規化).
  double get height => bottom - top;

  /// フル領域(クロップ不要)かどうか.
  bool get isFull => left <= 0.0 && top <= 0.0 && right >= 1.0 && bottom >= 1.0;

  /// 各値が有効範囲内(0.0–1.0,left<right,top<bottom)かどうか.
  bool get isValid =>
      left >= 0.0 &&
      left < right &&
      right <= 1.0 &&
      top >= 0.0 &&
      top < bottom &&
      bottom <= 1.0;

  /// JSON マップから [PreviewRegion] を生成する.
  ///
  /// 値が数値でない/欠落している場合はフォールバック値(フル領域)を用いる.
  factory PreviewRegion.fromJson(Map<String, Object?> json) {
    double parse(Object? value, double fallback) {
      if (value is num) return value.toDouble();
      return fallback;
    }

    return PreviewRegion(
      left: parse(json['left'], full.left),
      top: parse(json['top'], full.top),
      right: parse(json['right'], full.right),
      bottom: parse(json['bottom'], full.bottom),
    );
  }
}