New implementation for calculateScanWindowRelativeToTextureInPercentage()
Showing
1 changed file
with
57 additions
and
37 deletions
| 1 | +import 'dart:math'; | ||
| 2 | + | ||
| 1 | import 'package:flutter/rendering.dart'; | 3 | import 'package:flutter/rendering.dart'; |
| 2 | 4 | ||
| 3 | /// the [scanWindow] rect will be relative and scaled to the [widgetSize] not the texture. so it is possible, | 5 | /// the [scanWindow] rect will be relative and scaled to the [widgetSize] not the texture. so it is possible, |
| @@ -14,57 +16,75 @@ Rect calculateScanWindowRelativeToTextureInPercentage( | @@ -14,57 +16,75 @@ Rect calculateScanWindowRelativeToTextureInPercentage( | ||
| 14 | Size textureSize, | 16 | Size textureSize, |
| 15 | Size widgetSize, | 17 | Size widgetSize, |
| 16 | ) { | 18 | ) { |
| 17 | - double fittedTextureWidth; | ||
| 18 | - double fittedTextureHeight; | 19 | + /// map the texture size to get its new size after fitted to screen |
| 20 | + final fittedTextureSize = applyBoxFit(fit, textureSize, widgetSize); | ||
| 21 | + | ||
| 22 | + // Get the correct scaling values depending on the given BoxFit mode | ||
| 23 | + double sx = fittedTextureSize.destination.width / textureSize.width; | ||
| 24 | + double sy = fittedTextureSize.destination.height / textureSize.height; | ||
| 19 | 25 | ||
| 20 | switch (fit) { | 26 | switch (fit) { |
| 27 | + case BoxFit.fill: | ||
| 28 | + // nop | ||
| 29 | + // Just use sx and sy | ||
| 30 | + break; | ||
| 21 | case BoxFit.contain: | 31 | case BoxFit.contain: |
| 22 | - final widthRatio = widgetSize.width / textureSize.width; | ||
| 23 | - final heightRatio = widgetSize.height / textureSize.height; | ||
| 24 | - final scale = widthRatio < heightRatio ? widthRatio : heightRatio; | ||
| 25 | - fittedTextureWidth = textureSize.width * scale; | ||
| 26 | - fittedTextureHeight = textureSize.height * scale; | 32 | + final s = min(sx, sy); |
| 33 | + sx = s; | ||
| 34 | + sy = s; | ||
| 27 | break; | 35 | break; |
| 28 | - | ||
| 29 | case BoxFit.cover: | 36 | case BoxFit.cover: |
| 30 | - final widthRatio = widgetSize.width / textureSize.width; | ||
| 31 | - final heightRatio = widgetSize.height / textureSize.height; | ||
| 32 | - final scale = widthRatio > heightRatio ? widthRatio : heightRatio; | ||
| 33 | - fittedTextureWidth = textureSize.width * scale; | ||
| 34 | - fittedTextureHeight = textureSize.height * scale; | 37 | + final s = max(sx, sy); |
| 38 | + sx = s; | ||
| 39 | + sy = s; | ||
| 35 | break; | 40 | break; |
| 36 | - | ||
| 37 | - case BoxFit.fill: | ||
| 38 | - fittedTextureWidth = widgetSize.width; | ||
| 39 | - fittedTextureHeight = widgetSize.height; | 41 | + case BoxFit.fitWidth: |
| 42 | + sy = sx; | ||
| 40 | break; | 43 | break; |
| 41 | - | ||
| 42 | case BoxFit.fitHeight: | 44 | case BoxFit.fitHeight: |
| 43 | - final ratio = widgetSize.height / textureSize.height; | ||
| 44 | - fittedTextureWidth = textureSize.width * ratio; | ||
| 45 | - fittedTextureHeight = widgetSize.height; | ||
| 46 | - break; | ||
| 47 | - | ||
| 48 | - case BoxFit.fitWidth: | ||
| 49 | - final ratio = widgetSize.width / textureSize.width; | ||
| 50 | - fittedTextureWidth = widgetSize.width; | ||
| 51 | - fittedTextureHeight = textureSize.height * ratio; | 45 | + sx = sy; |
| 52 | break; | 46 | break; |
| 53 | - | ||
| 54 | case BoxFit.none: | 47 | case BoxFit.none: |
| 48 | + sx = 1.0; | ||
| 49 | + sy = 1.0; | ||
| 50 | + break; | ||
| 55 | case BoxFit.scaleDown: | 51 | case BoxFit.scaleDown: |
| 56 | - fittedTextureWidth = textureSize.width; | ||
| 57 | - fittedTextureHeight = textureSize.height; | 52 | + final s = min(sx, sy); |
| 53 | + sx = s; | ||
| 54 | + sy = s; | ||
| 58 | break; | 55 | break; |
| 59 | } | 56 | } |
| 60 | 57 | ||
| 61 | - final offsetX = (widgetSize.width - fittedTextureWidth) / 2; | ||
| 62 | - final offsetY = (widgetSize.height - fittedTextureHeight) / 2; | 58 | + // Fit the texture size to the widget rectangle given by the scaling values above |
| 59 | + final textureWindow = Alignment.center.inscribe( | ||
| 60 | + Size(textureSize.width * sx, textureSize.height * sy), | ||
| 61 | + Rect.fromLTWH(0, 0, widgetSize.width, widgetSize.height), | ||
| 62 | + ); | ||
| 63 | + | ||
| 64 | + // Transform the scan window from widget coordinates to texture coordinates | ||
| 65 | + final scanWindowInTexSpace = Rect.fromLTRB( | ||
| 66 | + (1 / sx) * (scanWindow.left - textureWindow.left), | ||
| 67 | + (1 / sy) * (scanWindow.top - textureWindow.top), | ||
| 68 | + (1 / sx) * (scanWindow.right - textureWindow.left), | ||
| 69 | + (1 / sy) * (scanWindow.bottom - textureWindow.top), | ||
| 70 | + ); | ||
| 71 | + | ||
| 72 | + // Clip the scan window in texture coordinates with the texture bounds. | ||
| 73 | + // This prevents percentages outside the range [0; 1]. | ||
| 74 | + final clippedScanWndInTexSpace = scanWindowInTexSpace | ||
| 75 | + .intersect(Rect.fromLTWH(0, 0, textureSize.width, textureSize.height)); | ||
| 63 | 76 | ||
| 64 | - final left = (scanWindow.left - offsetX) / fittedTextureWidth; | ||
| 65 | - final top = (scanWindow.top - offsetY) / fittedTextureHeight; | ||
| 66 | - final right = (scanWindow.right - offsetX) / fittedTextureWidth; | ||
| 67 | - final bottom = (scanWindow.bottom - offsetY) / fittedTextureHeight; | 77 | + // Compute relative rectangle coordinates with respect to the texture size, i.e. scan image |
| 78 | + final percentageLeft = clippedScanWndInTexSpace.left / textureSize.width; | ||
| 79 | + final percentageTop = clippedScanWndInTexSpace.top / textureSize.height; | ||
| 80 | + final percentageRight = clippedScanWndInTexSpace.right / textureSize.width; | ||
| 81 | + final percentageBottom = clippedScanWndInTexSpace.bottom / textureSize.height; | ||
| 68 | 82 | ||
| 69 | - return Rect.fromLTRB(left, top, right, bottom); | 83 | + // This rectangle can be send to native code and used to cut out a rectangle of the scan image |
| 84 | + return Rect.fromLTRB( | ||
| 85 | + percentageLeft, | ||
| 86 | + percentageTop, | ||
| 87 | + percentageRight, | ||
| 88 | + percentageBottom, | ||
| 89 | + ); | ||
| 70 | } | 90 | } |
-
Please register or login to post a comment