1// Copyright 2016-present 650 Industries. All rights reserved.
2
3#import <UIKit/UIKit.h>
4#import <AVFoundation/AVFoundation.h>
5#import <ZXingObjC/ZXingObjCCore.h>
6#import <EXBarCodeScanner/EXBarCodeScannerUtils.h>
7
8@implementation EXBarCodeScannerUtils
9
10+ (NSDictionary *)validBarCodeTypes
11{
12    NSMutableDictionary *validTypes = [@{
13      @"upc_e" : AVMetadataObjectTypeUPCECode,
14      @"code39" : AVMetadataObjectTypeCode39Code,
15      @"code39mod43" : AVMetadataObjectTypeCode39Mod43Code,
16      @"ean13" : AVMetadataObjectTypeEAN13Code,
17      @"ean8" : AVMetadataObjectTypeEAN8Code,
18      @"code93" : AVMetadataObjectTypeCode93Code,
19      @"code128" : AVMetadataObjectTypeCode128Code,
20      @"pdf417" : AVMetadataObjectTypePDF417Code,
21      @"qr" : AVMetadataObjectTypeQRCode,
22      @"aztec" : AVMetadataObjectTypeAztecCode,
23      @"interleaved2of5" : AVMetadataObjectTypeInterleaved2of5Code,
24      @"itf14" : AVMetadataObjectTypeITF14Code,
25      @"datamatrix" : AVMetadataObjectTypeDataMatrixCode,
26    } mutableCopy];
27#ifdef __IPHONE_15_4
28    if (@available(iOS 15.4, *)) {
29      validTypes[@"codabar"] = AVMetadataObjectTypeCodabarCode;
30    }
31#endif
32    return validTypes;
33}
34
35+ (AVCaptureVideoOrientation)videoOrientationForInterfaceOrientation:(UIInterfaceOrientation)orientation
36{
37  switch (orientation) {
38    case UIInterfaceOrientationPortrait:
39      return AVCaptureVideoOrientationPortrait;
40    case UIInterfaceOrientationPortraitUpsideDown:
41      return AVCaptureVideoOrientationPortraitUpsideDown;
42    case UIInterfaceOrientationLandscapeRight:
43      return AVCaptureVideoOrientationLandscapeRight;
44    case UIInterfaceOrientationLandscapeLeft:
45      return AVCaptureVideoOrientationLandscapeLeft;
46    default:
47      return 0;
48  }
49}
50
51+ (AVCaptureDevice *)deviceWithMediaType:(AVMediaType)mediaType
52                      preferringPosition:(AVCaptureDevicePosition)position
53{
54  return [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:mediaType position:position];
55}
56
57+ (NSDictionary *)ciQRCodeFeatureToDicitionary:(CIQRCodeFeature *)barCodeScannerResult barCodeType:(NSString *)type
58{
59  NSMutableDictionary *result = [NSMutableDictionary new];
60  result[@"type"] = type;
61  result[@"data"] = barCodeScannerResult.messageString;
62
63  if (!CGRectIsEmpty(barCodeScannerResult.bounds)) {
64    NSMutableArray<NSDictionary *> *cornerPointsResult = [NSMutableArray new];
65    for (NSValue *nsPoint in @[
66      [NSValue valueWithCGPoint:barCodeScannerResult.topLeft],
67      [NSValue valueWithCGPoint:barCodeScannerResult.topRight],
68      [NSValue valueWithCGPoint:barCodeScannerResult.bottomRight],
69      [NSValue valueWithCGPoint:barCodeScannerResult.bottomLeft]
70    ]) {
71      CGPoint point = [nsPoint CGPointValue];
72      [cornerPointsResult addObject:@{
73        @"x": @(point.x),
74        @"y": @(point.y)
75      }];
76    }
77
78    result[@"cornerPoints"] = cornerPointsResult;
79    result[@"bounds"] = @{
80      @"origin": @{
81        @"x": @(barCodeScannerResult.bounds.origin.x),
82        @"y": @(barCodeScannerResult.bounds.origin.y),
83      },
84      @"size": @{
85        @"width": @(barCodeScannerResult.bounds.size.width),
86        @"height": @(barCodeScannerResult.bounds.size.height),
87      }
88    };
89  } else {
90    [EXBarCodeScannerUtils addEmptyCornerPoints:result];
91  }
92
93  return result;
94}
95
96+ (NSDictionary *)avMetadataCodeObjectToDicitionary:(AVMetadataMachineReadableCodeObject *)barCodeScannerResult
97{
98  NSMutableDictionary *result = [NSMutableDictionary new];
99  result[@"type"] = barCodeScannerResult.type;
100  result[@"data"] = barCodeScannerResult.stringValue;
101
102  if (barCodeScannerResult.corners.count) {
103    NSMutableArray<NSDictionary *> *cornerPointsResult = [NSMutableArray new];
104    for (NSDictionary *point in barCodeScannerResult.corners) {
105      [cornerPointsResult addObject:@{
106        @"x": point[@"X"],
107        @"y": point[@"Y"]
108      }];
109    }
110    result[@"cornerPoints"] = cornerPointsResult;
111    result[@"bounds"] = @{
112      @"origin": @{
113        @"x": @(barCodeScannerResult.bounds.origin.x),
114        @"y": @(barCodeScannerResult.bounds.origin.y),
115      },
116      @"size": @{
117        @"width": @(barCodeScannerResult.bounds.size.width),
118        @"height": @(barCodeScannerResult.bounds.size.height),
119      }
120    };
121  } else {
122    [EXBarCodeScannerUtils addEmptyCornerPoints:result];
123  }
124  return result;
125}
126
127+ (NSDictionary *)zxResultToDicitionary:(ZXResult *)barCodeScannerResult
128{
129  NSMutableDictionary *result = [NSMutableDictionary new];
130  result[@"type"] = [EXBarCodeScannerUtils zxingFormatToString:barCodeScannerResult.barcodeFormat];
131
132  // text contains characteres u'\0' (null character) that malforme resulting string, so we get rid of them
133  NSMutableString* data = [NSMutableString new];
134  for (int i = 0; i < [barCodeScannerResult.text length]; i++) {
135    if ([barCodeScannerResult.text characterAtIndex:i] != u'\0') {
136      [data appendFormat:@"%c", [barCodeScannerResult.text characterAtIndex:i]];
137    }
138  }
139  result[@"data"] = data;
140
141  return result;
142}
143
144+ (NSString *)zxingFormatToString:(ZXBarcodeFormat)format
145{
146  switch (format) {
147    case kBarcodeFormatPDF417:
148      return AVMetadataObjectTypePDF417Code;
149    case kBarcodeFormatCode39:
150      return AVMetadataObjectTypeCode39Code;
151    case kBarcodeFormatCodabar:
152#ifdef __IPHONE_15_4
153      if (@available(iOS 15.4, *)) {
154        return AVMetadataObjectTypeCodabarCode;
155      }
156#endif
157      return @"unknown";
158    default:
159      return @"unknown";
160  }
161}
162
163+ (void)addEmptyCornerPoints:(NSMutableDictionary *)result
164{
165  result[@"cornerPoints"] = @[];
166  result[@"bounds"] = @{
167    @"origin": @{
168      @"x": @(0),
169      @"y": @(0),
170    },
171    @"size": @{
172      @"width": @(0),
173      @"height": @(0),
174    }
175  };
176}
177
178@end
179