diff --git a/analysis_options.yaml b/analysis_options.yaml index 82b26a2..2607df3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -80,7 +80,6 @@ linter: # libraries # classes - one_member_abstracts # avoid - - avoid_classes_with_only_static_members # avoid - public_member_api_docs # constructors - prefer_constructors_over_static_methods diff --git a/lib/src/errors.dart b/lib/src/errors.dart index 5068cb2..239b9ea 100644 --- a/lib/src/errors.dart +++ b/lib/src/errors.dart @@ -13,7 +13,7 @@ import 'qr_versions.dart'; class QrUnsupportedVersionException implements Exception { /// Create a new QrUnsupportedVersionException. factory QrUnsupportedVersionException(int providedVersion) { - final String message = + final message = 'Invalid version. $providedVersion is not >= ${QrVersions.min} ' 'and <= ${QrVersions.max}'; return QrUnsupportedVersionException._internal(providedVersion, message); diff --git a/lib/src/paint_cache.dart b/lib/src/paint_cache.dart index 454ee36..ead3df3 100644 --- a/lib/src/paint_cache.dart +++ b/lib/src/paint_cache.dart @@ -8,12 +8,14 @@ import 'package:flutter/widgets.dart'; import 'types.dart'; +/// Caches painter objects so we do have to recreate them and waste expensive +/// cycles. class PaintCache { final List _pixelPaints = []; final Map _keyedPaints = {}; String _cacheKey(QrCodeElement element, {FinderPatternPosition? position}) { - final String posKey = position != null ? position.toString() : 'any'; + final posKey = position != null ? position.toString() : 'any'; return '$element:$posKey'; } diff --git a/lib/src/qr_image_view.dart b/lib/src/qr_image_view.dart index 809e742..e803f5c 100644 --- a/lib/src/qr_image_view.dart +++ b/lib/src/qr_image_view.dart @@ -178,20 +178,20 @@ class _QrImageViewState extends State { QrValidationResult(status: QrValidationStatus.valid, qrCode: _qr); } return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { + builder: (context, constraints) { // validation failed, show an error state widget if builder is present. if (!_validationResult.isValid) { return _errorWidget(context, constraints, _validationResult.error); } // no error, build the regular widget - final double widgetSize = + final widgetSize = widget.size ?? constraints.biggest.shortestSide; if (widget.embeddedImage != null) { // if requesting to embed an image then we need to load via a // FutureBuilder because the image provider will be async. return FutureBuilder( future: _loadQrImage(context, widget.embeddedImageStyle), - builder: (BuildContext ctx, AsyncSnapshot snapshot) { + builder: (ctx, snapshot) { if (snapshot.error != null) { debugPrint('snapshot error: ${snapshot.error}'); return widget.embeddedImageEmitsError @@ -200,7 +200,7 @@ class _QrImageViewState extends State { } if (snapshot.hasData) { debugPrint('loaded image'); - final ui.Image? loadedImage = snapshot.data; + final loadedImage = snapshot.data; return _qrWidget(loadedImage, widgetSize); } else { return Container(); @@ -215,7 +215,7 @@ class _QrImageViewState extends State { } Widget _qrWidget(ui.Image? image, double edgeLength) { - final QrPainter painter = QrPainter.withQr( + final painter = QrPainter.withQr( qr: _qr!, // ignore: deprecated_member_use_from_same_package color: widget.foregroundColor, @@ -239,10 +239,10 @@ class _QrImageViewState extends State { BoxConstraints constraints, Object? error, ) { - final Widget errorWidget = widget.errorStateBuilder == null + final errorWidget = widget.errorStateBuilder == null ? Container() : widget.errorStateBuilder!(context, error); - final double errorSideLength = widget.constrainErrorBounds + final errorSideLength = widget.constrainErrorBounds ? widget.size ?? constraints.biggest.shortestSide : constraints.biggest.longestSide; return _QrContentView( @@ -262,20 +262,20 @@ class _QrImageViewState extends State { ) { if (style != null) {} - final MediaQueryData mq = MediaQuery.of(buildContext); - final Completer completer = Completer(); - final ImageStream stream = widget.embeddedImage!.resolve( + final mq = MediaQuery.of(buildContext); + final completer = Completer(); + final stream = widget.embeddedImage!.resolve( ImageConfiguration( devicePixelRatio: mq.devicePixelRatio, ), ); streamListener = ImageStreamListener( - (ImageInfo info, bool err) { + (info, err) { stream.removeListener(streamListener); completer.complete(info.image); }, - onError: (Object err, _) { + onError: (err, _) { stream.removeListener(streamListener); completer.completeError(err); }, diff --git a/lib/src/qr_painter.dart b/lib/src/qr_painter.dart index be754b3..f2f3ba2 100644 --- a/lib/src/qr_painter.dart +++ b/lib/src/qr_painter.dart @@ -138,7 +138,7 @@ class QrPainter extends CustomPainter { throw QrUnsupportedVersionException(version); } // configure and make the QR code data - final QrValidationResult validationResult = QrValidator.validate( + final validationResult = QrValidator.validate( data: data, version: version, errorCorrectionLevel: errorCorrectionLevel, @@ -168,7 +168,7 @@ class QrPainter extends CustomPainter { ); // Cache the finder pattern painters. We'll keep one for each one in case // we want to provide customization options later. - for (final FinderPatternPosition position in FinderPatternPosition.values) { + for (final position in FinderPatternPosition.values) { _paintCache.cache( Paint()..style = PaintingStyle.stroke, QrCodeElement.finderPatternOuter, @@ -197,7 +197,7 @@ class QrPainter extends CustomPainter { return; } - final _PaintMetrics paintMetrics = _PaintMetrics( + final paintMetrics = _PaintMetrics( containerSize: size.shortestSide, moduleCount: _qr!.moduleCount, gapSize: gapless ? 0 : _gapSize, @@ -231,9 +231,9 @@ class QrPainter extends CustomPainter { double left; double top; - final num gap = !gapless ? _gapSize : 0; + final gap = !gapless ? _gapSize : 0; // get the painters for the pixel information - final ui.Paint? pixelPaint = + final pixelPaint = _paintCache.firstPaint(QrCodeElement.codePixel); if (color != null) { pixelPaint!.color = color!; @@ -245,13 +245,13 @@ class QrPainter extends CustomPainter { emptyPixelPaint = _paintCache.firstPaint(QrCodeElement.codePixelEmpty); emptyPixelPaint!.color = emptyColor!; } - for (int x = 0; x < _qr!.moduleCount; x++) { - for (int y = 0; y < _qr!.moduleCount; y++) { + for (var x = 0; x < _qr!.moduleCount; x++) { + for (var y = 0; y < _qr!.moduleCount; y++) { // draw the finder patterns independently if (_isFinderPatternPosition(x, y)) { continue; } - final ui.Paint? paint = + final paint = _qrImage.isDark(y, x) ? pixelPaint : emptyPixelPaint; if (paint == null) { continue; @@ -259,15 +259,15 @@ class QrPainter extends CustomPainter { // paint a pixel left = paintMetrics.inset + (x * (paintMetrics.pixelSize + gap)); top = paintMetrics.inset + (y * (paintMetrics.pixelSize + gap)); - double pixelHTweak = 0.0; - double pixelVTweak = 0.0; + var pixelHTweak = 0.0; + var pixelVTweak = 0.0; if (gapless && _hasAdjacentHorizontalPixel(x, y, _qr!.moduleCount)) { pixelHTweak = 0.5; } if (gapless && _hasAdjacentVerticalPixel(x, y, _qr!.moduleCount)) { pixelVTweak = 0.5; } - final ui.Rect squareRect = Rect.fromLTWH( + final squareRect = Rect.fromLTWH( left, top, paintMetrics.pixelSize + pixelHTweak, @@ -276,7 +276,7 @@ class QrPainter extends CustomPainter { if (dataModuleStyle.dataModuleShape == QrDataModuleShape.square) { canvas.drawRect(squareRect, paint); } else { - final ui.RRect roundedRect = RRect.fromRectAndRadius( + final roundedRect = RRect.fromRectAndRadius( squareRect, Radius.circular(paintMetrics.pixelSize + pixelHTweak), ); @@ -286,15 +286,15 @@ class QrPainter extends CustomPainter { } if (embeddedImage != null) { - final ui.Size originalSize = Size( + final originalSize = Size( embeddedImage!.width.toDouble(), embeddedImage!.height.toDouble(), ); - final ui.Size? requestedSize = + final requestedSize = embeddedImageStyle != null ? embeddedImageStyle!.size : null; - final ui.Size imageSize = + final imageSize = _scaledAspectSize(size, originalSize, requestedSize); - final ui.Offset position = Offset( + final position = Offset( (size.width - imageSize.width) / 2.0, (size.height - imageSize.height) / 2.0, ); @@ -318,10 +318,10 @@ class QrPainter extends CustomPainter { } bool _isFinderPatternPosition(int x, int y) { - final bool isTopLeft = y < _finderPatternLimit && x < _finderPatternLimit; - final bool isBottomLeft = y < _finderPatternLimit && + final isTopLeft = y < _finderPatternLimit && x < _finderPatternLimit; + final isBottomLeft = y < _finderPatternLimit && (x >= _qr!.moduleCount - _finderPatternLimit); - final bool isTopRight = y >= _qr!.moduleCount - _finderPatternLimit && + final isTopRight = y >= _qr!.moduleCount - _finderPatternLimit && (x < _finderPatternLimit); return isTopLeft || isBottomLeft || isTopRight; } @@ -331,12 +331,12 @@ class QrPainter extends CustomPainter { Canvas canvas, _PaintMetrics metrics, ) { - final double totalGap = (_finderPatternLimit - 1) * metrics.gapSize; - final double radius = + final totalGap = (_finderPatternLimit - 1) * metrics.gapSize; + final radius = ((_finderPatternLimit * metrics.pixelSize) + totalGap) - metrics.pixelSize; - final double strokeAdjust = metrics.pixelSize / 2.0; - final double edgePos = + final strokeAdjust = metrics.pixelSize / 2.0; + final edgePos = (metrics.inset + metrics.innerContentSize) - (radius + strokeAdjust); Offset offset; @@ -350,19 +350,19 @@ class QrPainter extends CustomPainter { } // configure the paints - final ui.Paint outerPaint = _paintCache.firstPaint( + final outerPaint = _paintCache.firstPaint( QrCodeElement.finderPatternOuter, position: position, )!; outerPaint.strokeWidth = metrics.pixelSize; outerPaint.color = color != null ? color! : eyeStyle.color!; - final ui.Paint innerPaint = _paintCache + final innerPaint = _paintCache .firstPaint(QrCodeElement.finderPatternInner, position: position)!; innerPaint.strokeWidth = metrics.pixelSize; innerPaint.color = emptyColor ?? const Color(0x00ffffff); - final ui.Paint? dotPaint = _paintCache.firstPaint( + final dotPaint = _paintCache.firstPaint( QrCodeElement.finderPatternDot, position: position, ); @@ -372,20 +372,20 @@ class QrPainter extends CustomPainter { dotPaint!.color = eyeStyle.color!; } - final ui.Rect outerRect = + final outerRect = Rect.fromLTWH(offset.dx, offset.dy, radius, radius); - final double innerRadius = radius - (2 * metrics.pixelSize); - final ui.Rect innerRect = Rect.fromLTWH( + final innerRadius = radius - (2 * metrics.pixelSize); + final innerRect = Rect.fromLTWH( offset.dx + metrics.pixelSize, offset.dy + metrics.pixelSize, innerRadius, innerRadius, ); - final double gap = metrics.pixelSize * 2; - final double dotSize = radius - gap - (2 * strokeAdjust); - final ui.Rect dotRect = Rect.fromLTWH( + final gap = metrics.pixelSize * 2; + final dotSize = radius - gap - (2 * strokeAdjust); + final dotRect = Rect.fromLTWH( offset.dx + metrics.pixelSize + strokeAdjust, offset.dy + metrics.pixelSize + strokeAdjust, dotSize, @@ -397,15 +397,15 @@ class QrPainter extends CustomPainter { canvas.drawRect(innerRect, innerPaint); canvas.drawRect(dotRect, dotPaint); } else { - final ui.RRect roundedOuterStrokeRect = + final roundedOuterStrokeRect = RRect.fromRectAndRadius(outerRect, Radius.circular(radius)); canvas.drawRRect(roundedOuterStrokeRect, outerPaint); - final ui.RRect roundedInnerStrokeRect = + final roundedInnerStrokeRect = RRect.fromRectAndRadius(outerRect, Radius.circular(innerRadius)); canvas.drawRRect(roundedInnerStrokeRect, innerPaint); - final ui.RRect roundedDotStrokeRect = + final roundedDotStrokeRect = RRect.fromRectAndRadius(dotRect, Radius.circular(dotSize)); canvas.drawRRect(roundedDotStrokeRect, dotPaint); } @@ -421,12 +421,12 @@ class QrPainter extends CustomPainter { if (requestedSize != null && !requestedSize.isEmpty) { return requestedSize; } else if (requestedSize != null && _hasOneNonZeroSide(requestedSize)) { - final double maxSide = requestedSize.longestSide; - final double ratio = maxSide / originalSize.longestSide; + final maxSide = requestedSize.longestSide; + final ratio = maxSide / originalSize.longestSide; return Size(ratio * originalSize.width, ratio * originalSize.height); } else { - final double maxSide = 0.25 * widgetSize.shortestSide; - final double ratio = maxSide / originalSize.longestSide; + final maxSide = 0.25 * widgetSize.shortestSide; + final ratio = maxSide / originalSize.longestSide; return Size(ratio * originalSize.width, ratio * originalSize.height); } } @@ -437,7 +437,7 @@ class QrPainter extends CustomPainter { Size size, QrEmbeddedImageStyle? style, ) { - final ui.Paint paint = Paint() + final paint = Paint() ..isAntiAlias = true ..filterQuality = FilterQuality.high; if (style != null) { @@ -445,11 +445,11 @@ class QrPainter extends CustomPainter { paint.colorFilter = ColorFilter.mode(style.color!, BlendMode.srcATop); } } - final ui.Size srcSize = + final srcSize = Size(embeddedImage!.width.toDouble(), embeddedImage!.height.toDouble()); - final ui.Rect src = + final src = Alignment.center.inscribe(srcSize, Offset.zero & srcSize); - final ui.Rect dst = Alignment.center.inscribe(size, position & size); + final dst = Alignment.center.inscribe(size, position & size); canvas.drawImageRect(embeddedImage!, src, dst, paint); } @@ -470,8 +470,8 @@ class QrPainter extends CustomPainter { /// Returns a [ui.Picture] object containing the QR code data. ui.Picture toPicture(double size) { - final ui.PictureRecorder recorder = ui.PictureRecorder(); - final ui.Canvas canvas = Canvas(recorder); + final recorder = ui.PictureRecorder(); + final canvas = Canvas(recorder); paint(canvas, Size(size, size)); return recorder.endRecording(); } @@ -486,7 +486,7 @@ class QrPainter extends CustomPainter { double size, { ui.ImageByteFormat format = ui.ImageByteFormat.png, }) async { - final ui.Image image = await toImage(size); + final image = await toImage(size); return image.toByteData(format: format); } } @@ -514,8 +514,8 @@ class _PaintMetrics { double get inset => _inset; void _calculateMetrics() { - final double gapTotal = (moduleCount - 1) * gapSize; - final double pixelSize = (containerSize - gapTotal) / moduleCount; + final gapTotal = (moduleCount - 1) * gapSize; + final pixelSize = (containerSize - gapTotal) / moduleCount; _pixelSize = (pixelSize * 2).roundToDouble() / 2; _innerContentSize = (_pixelSize * moduleCount) + gapTotal; _inset = (containerSize - _innerContentSize) / 2; diff --git a/test/image_test.dart b/test/image_test.dart index 565fe3e..578c1c8 100644 --- a/test/image_test.dart +++ b/test/image_test.dart @@ -12,9 +12,9 @@ import 'package:qr_flutter/qr_flutter.dart'; void main() { testWidgets('QrImageView generates correct image', ( - WidgetTester tester, + tester, ) async { - final MaterialApp qrImage = MaterialApp( + final qrImage = MaterialApp( home: Center( child: RepaintBoundary( child: QrImageView( @@ -35,8 +35,8 @@ void main() { testWidgets( 'QrImageView generates correct image with eye style', - (WidgetTester tester) async { - final MaterialApp qrImage = MaterialApp( + (tester) async { + final qrImage = MaterialApp( home: Center( child: RepaintBoundary( child: QrImageView( @@ -62,8 +62,8 @@ void main() { testWidgets( 'QrImageView generates correct image with data module style', - (WidgetTester tester) async { - final MaterialApp qrImage = MaterialApp( + (tester) async { + final qrImage = MaterialApp( home: Center( child: RepaintBoundary( child: QrImageView( @@ -89,8 +89,8 @@ void main() { testWidgets( 'QrImageView generates correct image with eye and data module sytle', - (WidgetTester tester) async { - final MaterialApp qrImage = MaterialApp( + (tester) async { + final qrImage = MaterialApp( home: Center( child: RepaintBoundary( child: QrImageView( @@ -123,8 +123,8 @@ void main() { testWidgets( 'QrImageView does not apply eye and data module color when foreground ' 'color is also specified', - (WidgetTester tester) async { - final MaterialApp qrImage = MaterialApp( + (tester) async { + final qrImage = MaterialApp( home: Center( child: RepaintBoundary( child: QrImageView( @@ -156,7 +156,7 @@ void main() { testWidgets( 'QrImageView generates correct image with logo', - (WidgetTester tester) async { + (tester) async { await pumpWidgetWithImages( tester, MaterialApp( @@ -196,7 +196,7 @@ Future pumpWidgetWithImages( Future? precacheFuture; await tester.pumpWidget( Builder( - builder: (BuildContext buildContext) { + builder: (buildContext) { precacheFuture = tester.runAsync(() async { await Future.wait(>[ for (final String assetName in assetNames) diff --git a/test/painter_test.dart b/test/painter_test.dart index dcc0942..3e292c9 100644 --- a/test/painter_test.dart +++ b/test/painter_test.dart @@ -10,8 +10,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:qr_flutter/qr_flutter.dart'; void main() { - testWidgets('QrPainter generates correct image', (WidgetTester tester) async { - final QrPainter painter = QrPainter( + testWidgets('QrPainter generates correct image', (tester) async { + final painter = QrPainter( data: 'The painter is this thing', version: QrVersions.auto, gapless: true, @@ -21,7 +21,7 @@ void main() { await tester.runAsync(() async { imageData = await painter.toImageData(600.0); }); - final Uint8List imageBytes = imageData!.buffer.asUint8List(); + final imageBytes = imageData!.buffer.asUint8List(); final Widget widget = Center( child: RepaintBoundary( child: SizedBox(