375 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			375 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Dart
		
	
	
/// Created by @Haoyi on 2021/7/7
 | 
						|
///
 | 
						|
 | 
						|
part of "design.dart";
 | 
						|
 | 
						|
class _DeviceMetrics {
 | 
						|
  final double wScale;
 | 
						|
  final double hScale;
 | 
						|
  final Size size;
 | 
						|
  final TextDirection? direction;
 | 
						|
  final Offset offset;
 | 
						|
  final SystemAdaptation? adaptation;
 | 
						|
 | 
						|
  const _DeviceMetrics(this.wScale, this.hScale, this.size, this.direction,
 | 
						|
      {this.offset = Offset.zero, this.adaptation});
 | 
						|
}
 | 
						|
 | 
						|
enum DesignFit { fitWidth, fitHeight, fill }
 | 
						|
 | 
						|
enum _DesignMethod {
 | 
						|
  width,
 | 
						|
  height,
 | 
						|
  average,
 | 
						|
  fontSize,
 | 
						|
  absoluteFontSize,
 | 
						|
  widthScale,
 | 
						|
  heightScale,
 | 
						|
  combine,
 | 
						|
  origin,
 | 
						|
  statusBarHeight,
 | 
						|
  wrappedInSafeAreaStatusBarHeight,
 | 
						|
  navigationBarHeight,
 | 
						|
  wrappedInSafeAreaNavigationBarHeight
 | 
						|
}
 | 
						|
 | 
						|
class SystemAdaptation {
 | 
						|
  final double? pixelRatio;
 | 
						|
 | 
						|
  final double? textScaleFactor;
 | 
						|
 | 
						|
  const SystemAdaptation({this.pixelRatio, this.textScaleFactor});
 | 
						|
 | 
						|
  static SystemAdaptation? defaultSystemAdaptation;
 | 
						|
 | 
						|
  static double? get globalPixelRation => defaultSystemAdaptation?.pixelRatio;
 | 
						|
 | 
						|
  static double? get globalTextScaleFactor => defaultSystemAdaptation?.textScaleFactor;
 | 
						|
}
 | 
						|
 | 
						|
class DesignMetrics {
 | 
						|
  Size designResolution = Size.zero;
 | 
						|
  final List<DesignObject> objects = [];
 | 
						|
  final SystemAdaptation? adaptation;
 | 
						|
  late Size measuredSize;
 | 
						|
 | 
						|
  static Map<num, DesignField> originFields = {
 | 
						|
    0: DesignField._origin(0),
 | 
						|
    1: DesignField._origin(1),
 | 
						|
    2: DesignField._origin(2),
 | 
						|
    3: DesignField._origin(3),
 | 
						|
    4: DesignField._origin(4),
 | 
						|
    5: DesignField._origin(5),
 | 
						|
    6: DesignField._origin(6),
 | 
						|
    7: DesignField._origin(7),
 | 
						|
    8: DesignField._origin(8),
 | 
						|
    9: DesignField._origin(9),
 | 
						|
  };
 | 
						|
 | 
						|
  DesignMetrics.create(this.designResolution, {this.adaptation});
 | 
						|
 | 
						|
  DesignMetrics.dynamic({this.adaptation}) : designResolution = Size.zero;
 | 
						|
 | 
						|
  DesignField origin(num value) {
 | 
						|
    final result = originFields[value];
 | 
						|
    if (result != null) {
 | 
						|
      return result;
 | 
						|
    }
 | 
						|
    final field = DesignField._origin(value);
 | 
						|
    originFields[value] = field;
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField designWidth(double size) {
 | 
						|
    final field = DesignField._width(size);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField designHorizontal(double size) {
 | 
						|
    final field = DesignField._width(size);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField designHeight(double size) {
 | 
						|
    final field = DesignField._height(size);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField designVertical(double size) {
 | 
						|
    final field = DesignField._height(size);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField designFontSize(double size) {
 | 
						|
    final field = DesignField._average(size);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField designAverageSize(double size) {
 | 
						|
    final field = DesignField._average(size);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField design(DesignField field) {
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField widthScale(double scale) {
 | 
						|
    final field = DesignField._widthScale(scale);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField heightScale(double scale) {
 | 
						|
    final field = DesignField._heightScale(scale);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField relativeRatio(DesignField relative, double ratio) {
 | 
						|
    final field = DesignField._relativeRatio(relative, ratio);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignSize designSize(double width, double height) {
 | 
						|
    final size = _DesignExplicitSize(width, height);
 | 
						|
    _add(size);
 | 
						|
    return size;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignSize designFieldSize(DesignField width, DesignField height) {
 | 
						|
    final size = _DesignFieldSize(width, height);
 | 
						|
    _add(size);
 | 
						|
    return size;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignSize widthRatioSize({required double width, required double ratio}) {
 | 
						|
    final size = _DesignWidthRatioSize(width, ratio);
 | 
						|
    _add(size);
 | 
						|
    return size;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignSize heightRatioSize({required double height, required double ratio}) {
 | 
						|
    final size = _DesignHeightRatioSize(height, ratio);
 | 
						|
    _add(size);
 | 
						|
    return size;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignRect fromLTRB(double left, double top, double right, double bottom) {
 | 
						|
    final rect = _DesignExplicitRect.fromLTRB(left, top, right, bottom);
 | 
						|
    _add(rect);
 | 
						|
    return rect;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignRect fromLTWH(double left, double top, double width, double height) {
 | 
						|
    return fromLTRB(left, top, left + width, top + height);
 | 
						|
  }
 | 
						|
 | 
						|
  DesignRect fromCenter(Offset center, double width, double height) {
 | 
						|
    return fromLTRB(center.dx - width * 0.5, center.dy - height * 0.5, center.dx + width * 0.5,
 | 
						|
        center.dy + height * 0.5);
 | 
						|
  }
 | 
						|
 | 
						|
  DesignRect fromFieldLTRB(
 | 
						|
      DesignField left, DesignField top, DesignField right, DesignField bottom) {
 | 
						|
    final rect = _DesignFieldRect.fromLTRB(left, top, right, bottom);
 | 
						|
    _add(rect);
 | 
						|
    return rect;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignRect fromFieldLTWH(
 | 
						|
      DesignField left, DesignField top, DesignField width, DesignField height) {
 | 
						|
    return fromFieldLTRB(left, top, left + width, top + height);
 | 
						|
  }
 | 
						|
 | 
						|
  DesignRect fromFieldCenter(
 | 
						|
      DesignField centerX, DesignField centerY, DesignField width, DesignField height) {
 | 
						|
    return fromFieldLTRB(
 | 
						|
        centerX - DesignField._relativeRatio(width, 0.5),
 | 
						|
        centerY - DesignField._relativeRatio(height, 0.5),
 | 
						|
        centerX + DesignField._relativeRatio(width, 0.5),
 | 
						|
        centerY + DesignField._relativeRatio(height, 0.5));
 | 
						|
  }
 | 
						|
 | 
						|
  DesignOffset fieldOffset(DesignField dx, DesignField dy) {
 | 
						|
    final offset = DesignOffset(dx, dy);
 | 
						|
    _add(offset);
 | 
						|
    return offset;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignOffset offset(double dx, double dy) {
 | 
						|
    return fieldOffset(designHorizontal(dx), designVertical(dy));
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField statusBarHeight({double defaultHeight = 0, bool wrappedInSafeArea = false}) {
 | 
						|
    final field = wrappedInSafeArea
 | 
						|
        ? DesignField.wrappedInSafeAreaStatusBarHeight(defaultHeight)
 | 
						|
        : DesignField.statusBarHeight(defaultHeight: defaultHeight);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField fakeStatusBarHeight({double fakeHeight = 0}) {
 | 
						|
    final field = DesignField.wrappedInSafeAreaStatusBarHeight(fakeHeight);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField navigationBarHeight({double defaultHeight = 0, bool wrappedInSafeArea = false}) {
 | 
						|
    final field = wrappedInSafeArea
 | 
						|
        ? DesignField.wrappedInSafeAreaNavigationBarHeight(defaultHeight)
 | 
						|
        : DesignField.navigationBarHeight(defaultHeight: defaultHeight);
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  DesignField combineAdd(DesignField field1, DesignField field2) {
 | 
						|
    final field = field1 + field2;
 | 
						|
    _add(field);
 | 
						|
    return field;
 | 
						|
  }
 | 
						|
 | 
						|
  void _add(DesignObject object) {
 | 
						|
    objects.add(object);
 | 
						|
  }
 | 
						|
 | 
						|
  MeasuredMetrics measure(Size size) {
 | 
						|
    measuredSize = size;
 | 
						|
    final deviceMetrics = _DeviceMetrics(
 | 
						|
        size.width / designResolution.width, size.height / designResolution.height, size, null,
 | 
						|
        adaptation: adaptation);
 | 
						|
    for (var field in objects) {
 | 
						|
      field.measure(deviceMetrics);
 | 
						|
    }
 | 
						|
    // print("size:$size designResolution:$designResolution ${deviceMetrics.wScale} ${deviceMetrics.hScale}");
 | 
						|
    return MeasuredMetrics(deviceMetrics, designResolution);
 | 
						|
  }
 | 
						|
 | 
						|
  MeasuredMetrics adaptiveMeasure(Size screenSize,
 | 
						|
      {DesignFit fit = DesignFit.fill, double scale = 1.0, double? limitSize, Size? designSize}) {
 | 
						|
    Size size;
 | 
						|
    designResolution = designSize ?? designResolution;
 | 
						|
    switch (fit) {
 | 
						|
      case DesignFit.fitWidth:
 | 
						|
        final newWidth = min(screenSize.width * scale, limitSize ?? screenSize.width);
 | 
						|
        final newHeight = newWidth * (designResolution.height / designResolution.width);
 | 
						|
        size = Size(newWidth, newHeight);
 | 
						|
        break;
 | 
						|
      case DesignFit.fitHeight:
 | 
						|
        final newHeight = screenSize.height * scale;
 | 
						|
        final newWidth = newHeight * (designResolution.width / designResolution.height);
 | 
						|
        size = Size(newWidth, newHeight);
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        size = screenSize;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return measure(size);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class MeasuredMetrics {
 | 
						|
  final _DeviceMetrics metrics;
 | 
						|
 | 
						|
  final Size designResolution;
 | 
						|
 | 
						|
  Size get size => metrics.size;
 | 
						|
 | 
						|
  double get measuredWidth => size.width;
 | 
						|
 | 
						|
  double get measuredHeight => size.height;
 | 
						|
 | 
						|
  // 宽高比
 | 
						|
  double get aspectRatio => size.width / size.height;
 | 
						|
 | 
						|
  double get designAspectRatio => designResolution.width / designResolution.height;
 | 
						|
 | 
						|
  double get deviceInverseAspectRatio => 1 / aspectRatio;
 | 
						|
 | 
						|
  double get designInverseAspectRatio => 1 / designAspectRatio;
 | 
						|
 | 
						|
  double get layoutHeightScaleFactor => designInverseAspectRatio / deviceInverseAspectRatio;
 | 
						|
 | 
						|
  double get layoutWidthScaleFactor => deviceInverseAspectRatio / designInverseAspectRatio;
 | 
						|
 | 
						|
  MeasuredMetrics(this.metrics, this.designResolution);
 | 
						|
 | 
						|
  Size measureSize(double width, double height) {
 | 
						|
    return Size(metrics.wScale * width, metrics.hScale * height);
 | 
						|
  }
 | 
						|
 | 
						|
  Offset measureOffset(double x, double y) {
 | 
						|
    return Offset(metrics.wScale * x, metrics.hScale * y);
 | 
						|
  }
 | 
						|
 | 
						|
  double measureWidth(double width, {bool consistent = false}) {
 | 
						|
    // 宽度暂不支持这个参数
 | 
						|
    return metrics.wScale * width;
 | 
						|
  }
 | 
						|
 | 
						|
  double measureHeight(double height, {bool consistent = false}) {
 | 
						|
    return metrics.hScale * height * (consistent ? layoutHeightScaleFactor : 1.0);
 | 
						|
  }
 | 
						|
 | 
						|
  double measureVertical(double vertical, {bool consistent = false}) {
 | 
						|
    return metrics.hScale * vertical * (consistent ? layoutHeightScaleFactor : 1.0);
 | 
						|
  }
 | 
						|
 | 
						|
  double measureHorizontal(double horizontal, {bool consistent = false}) {
 | 
						|
    // 宽度暂不支持这个参数
 | 
						|
    return metrics.wScale * horizontal;
 | 
						|
  }
 | 
						|
 | 
						|
  double measureFontSize(double fontSize) {
 | 
						|
    return DesignField._calculate(_DesignMethod.fontSize, metrics, fontSize);
 | 
						|
  }
 | 
						|
 | 
						|
  double measureAbsoluteFontSize(double fontSize, {bool consistent = false}) {
 | 
						|
    if (consistent) {
 | 
						|
      return fontSize *
 | 
						|
          metrics.hScale /
 | 
						|
          (metrics.adaptation?.textScaleFactor ?? Get.textScaleFactor);
 | 
						|
    }
 | 
						|
    return DesignField._calculate(_DesignMethod.absoluteFontSize, metrics, fontSize);
 | 
						|
  }
 | 
						|
 | 
						|
  double statusBarHeight(double ifAbsent) {
 | 
						|
    return DesignField._calculate(_DesignMethod.statusBarHeight, metrics, ifAbsent);
 | 
						|
  }
 | 
						|
 | 
						|
  double wrappedInSafeAreaStatusBarHeight(double ifAbsent) {
 | 
						|
    return DesignField._calculate(
 | 
						|
        _DesignMethod.wrappedInSafeAreaStatusBarHeight, metrics, ifAbsent);
 | 
						|
  }
 | 
						|
 | 
						|
  double navigationBarHeight(double navigationBarHeight) {
 | 
						|
    return DesignField._calculate(_DesignMethod.navigationBarHeight, metrics, navigationBarHeight);
 | 
						|
  }
 | 
						|
 | 
						|
  double relativeWidthRatio(double width, double ratio) {
 | 
						|
    return metrics.wScale * width * ratio;
 | 
						|
  }
 | 
						|
 | 
						|
  double relativeHeightRatio(double height, double ratio) {
 | 
						|
    return metrics.hScale * height * ratio;
 | 
						|
  }
 | 
						|
 | 
						|
  Rect fromLTWH(double left, double top, double width, double height) {
 | 
						|
    return Rect.fromLTWH(left * metrics.wScale, top * metrics.hScale, width * metrics.wScale,
 | 
						|
        height * metrics.hScale);
 | 
						|
  }
 | 
						|
 | 
						|
  Rect fromLTRB(double left, double top, double right, double bottom) {
 | 
						|
    return Rect.fromLTRB(left * metrics.wScale, top * metrics.hScale, right * metrics.wScale,
 | 
						|
        bottom * metrics.hScale);
 | 
						|
  }
 | 
						|
}
 |