Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zxing-cpp/core/src/ZXingC.cpp @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * Copyright 2023 siiky | |
| 3 * Copyright 2023 Axel Waggershauser | |
| 4 */ | |
| 5 // SPDX-License-Identifier: Apache-2.0 | |
| 6 | |
| 7 #include "ZXingC.h" | |
| 8 | |
| 9 #include "ZXingCpp.h" | |
| 10 #include "ZXConfig.h" | |
| 11 | |
| 12 #if __has_include("Version.h") | |
| 13 #include "Version.h" | |
| 14 #else // this is mainly a workaround for a missing autogenerated Version.h in the XCode/CocoaPods corner | |
| 15 #define ZXING_VERSION_STR "undefined" | |
| 16 #endif | |
| 17 | |
| 18 #include <cstdlib> | |
| 19 #include <exception> | |
| 20 #include <string> | |
| 21 #include <string_view> | |
| 22 #include <utility> | |
| 23 | |
| 24 using namespace ZXing; | |
| 25 | |
| 26 static ZX_THREAD_LOCAL std::string lastErrorMsg; | |
| 27 static Barcodes emptyBarcodes{}; // used to prevent new heap allocation for each empty result | |
| 28 | |
| 29 template<typename R, typename T> R transmute_cast(const T& v) noexcept | |
| 30 { | |
| 31 static_assert(sizeof(T) == sizeof(R)); | |
| 32 return *(const R*)(&v); | |
| 33 } | |
| 34 | |
| 35 template<typename C, typename P = typename C::pointer> | |
| 36 P copy(const C& c) noexcept | |
| 37 { | |
| 38 auto ret = (P)malloc(c.size() + 1); | |
| 39 if (ret) { | |
| 40 memcpy(ret, c.data(), c.size()); | |
| 41 ret[c.size()] = 0; | |
| 42 } | |
| 43 return ret; | |
| 44 } | |
| 45 | |
| 46 static uint8_t* copy(const ByteArray& ba, int* len) noexcept | |
| 47 { | |
| 48 // for convencience and as a safety measure, we NULL terminate even byte arrays | |
| 49 auto ret = copy(ba); | |
| 50 if (len) | |
| 51 *len = ret ? Size(ba) : 0; | |
| 52 return ret; | |
| 53 } | |
| 54 | |
| 55 #define ZX_CHECK( GOOD, MSG ) \ | |
| 56 if (!(GOOD)) { \ | |
| 57 lastErrorMsg = MSG; \ | |
| 58 return {}; \ | |
| 59 } | |
| 60 | |
| 61 #define ZX_CATCH(...) \ | |
| 62 catch (std::exception & e) { \ | |
| 63 lastErrorMsg = e.what(); \ | |
| 64 } catch (...) { \ | |
| 65 lastErrorMsg = "Unknown error"; \ | |
| 66 } \ | |
| 67 return __VA_ARGS__; | |
| 68 | |
| 69 #define ZX_TRY(...) \ | |
| 70 try { \ | |
| 71 return __VA_ARGS__; \ | |
| 72 } \ | |
| 73 ZX_CATCH({}) | |
| 74 | |
| 75 | |
| 76 extern "C" { | |
| 77 /* | |
| 78 * ZXing/ImageView.h | |
| 79 */ | |
| 80 | |
| 81 ZXing_ImageView* ZXing_ImageView_new(const uint8_t* data, int width, int height, ZXing_ImageFormat format, int rowStride, | |
| 82 int pixStride) | |
| 83 { | |
| 84 ImageFormat cppformat = static_cast<ImageFormat>(format); | |
| 85 ZX_TRY(new ImageView(data, width, height, cppformat, rowStride, pixStride)) | |
| 86 } | |
| 87 | |
| 88 ZXing_ImageView* ZXing_ImageView_new_checked(const uint8_t* data, int size, int width, int height, ZXing_ImageFormat format, | |
| 89 int rowStride, int pixStride) | |
| 90 { | |
| 91 ImageFormat cppformat = static_cast<ImageFormat>(format); | |
| 92 ZX_TRY(new ImageView(data, size, width, height, cppformat, rowStride, pixStride)) | |
| 93 } | |
| 94 | |
| 95 void ZXing_ImageView_delete(ZXing_ImageView* iv) | |
| 96 { | |
| 97 delete iv; | |
| 98 } | |
| 99 | |
| 100 void ZXing_ImageView_crop(ZXing_ImageView* iv, int left, int top, int width, int height) | |
| 101 { | |
| 102 *iv = iv->cropped(left, top, width, height); | |
| 103 } | |
| 104 | |
| 105 void ZXing_ImageView_rotate(ZXing_ImageView* iv, int degree) | |
| 106 { | |
| 107 *iv = iv->rotated(degree); | |
| 108 } | |
| 109 | |
| 110 void ZXing_Image_delete(ZXing_Image* img) | |
| 111 { | |
| 112 delete img; | |
| 113 } | |
| 114 | |
| 115 const uint8_t* ZXing_Image_data(const ZXing_Image* img) | |
| 116 { | |
| 117 return img->data(); | |
| 118 } | |
| 119 | |
| 120 int ZXing_Image_width(const ZXing_Image* img) | |
| 121 { | |
| 122 return img->width(); | |
| 123 } | |
| 124 | |
| 125 int ZXing_Image_height(const ZXing_Image* img) | |
| 126 { | |
| 127 return img->height(); | |
| 128 } | |
| 129 | |
| 130 ZXing_ImageFormat ZXing_Image_format(const ZXing_Image* img) | |
| 131 { | |
| 132 return static_cast<ZXing_ImageFormat>(img->format()); | |
| 133 } | |
| 134 | |
| 135 /* | |
| 136 * ZXing/BarcodeFormat.h | |
| 137 */ | |
| 138 | |
| 139 ZXing_BarcodeFormats ZXing_BarcodeFormatsFromString(const char* str) | |
| 140 { | |
| 141 if (!str) | |
| 142 return {}; | |
| 143 try { | |
| 144 return transmute_cast<ZXing_BarcodeFormats>(BarcodeFormatsFromString(str)); | |
| 145 } | |
| 146 ZX_CATCH(ZXing_BarcodeFormat_Invalid) | |
| 147 } | |
| 148 | |
| 149 ZXing_BarcodeFormat ZXing_BarcodeFormatFromString(const char* str) | |
| 150 { | |
| 151 ZXing_BarcodeFormat res = ZXing_BarcodeFormatsFromString(str); | |
| 152 return BitHacks::CountBitsSet(res) == 1 ? res : ZXing_BarcodeFormat_Invalid; | |
| 153 } | |
| 154 | |
| 155 char* ZXing_BarcodeFormatToString(ZXing_BarcodeFormat format) | |
| 156 { | |
| 157 return copy(ToString(static_cast<BarcodeFormat>(format))); | |
| 158 } | |
| 159 | |
| 160 /* | |
| 161 * ZXing/ZXingCpp.h | |
| 162 */ | |
| 163 | |
| 164 | |
| 165 #ifdef ZXING_EXPERIMENTAL_API | |
| 166 ZXing_BarcodeFormats ZXing_SupportedBarcodeFormats(ZXing_Operation op) | |
| 167 { | |
| 168 return transmute_cast<ZXing_BarcodeFormats>(SupportedBarcodeFormats(static_cast<Operation>(op))); | |
| 169 } | |
| 170 #endif | |
| 171 | |
| 172 /* | |
| 173 * ZXing/Barcode.h | |
| 174 */ | |
| 175 | |
| 176 char* ZXing_ContentTypeToString(ZXing_ContentType type) | |
| 177 { | |
| 178 return copy(ToString(static_cast<ContentType>(type))); | |
| 179 } | |
| 180 | |
| 181 char* ZXing_PositionToString(ZXing_Position position) | |
| 182 { | |
| 183 return copy(ToString(transmute_cast<Position>(position))); | |
| 184 } | |
| 185 | |
| 186 | |
| 187 bool ZXing_Barcode_isValid(const ZXing_Barcode* barcode) | |
| 188 { | |
| 189 return barcode != NULL && barcode->isValid(); | |
| 190 } | |
| 191 | |
| 192 ZXing_ErrorType ZXing_Barcode_errorType(const ZXing_Barcode* barcode) | |
| 193 { | |
| 194 return static_cast<ZXing_ErrorType>(barcode->error().type()); | |
| 195 } | |
| 196 | |
| 197 char* ZXing_Barcode_errorMsg(const ZXing_Barcode* barcode) | |
| 198 { | |
| 199 return copy(ToString(barcode->error())); | |
| 200 } | |
| 201 | |
| 202 uint8_t* ZXing_Barcode_bytes(const ZXing_Barcode* barcode, int* len) | |
| 203 { | |
| 204 return copy(barcode->bytes(), len); | |
| 205 } | |
| 206 | |
| 207 uint8_t* ZXing_Barcode_bytesECI(const ZXing_Barcode* barcode, int* len) | |
| 208 { | |
| 209 return copy(barcode->bytesECI(), len); | |
| 210 } | |
| 211 | |
| 212 #define ZX_GETTER(TYPE, GETTER, TRANS) \ | |
| 213 TYPE ZXing_Barcode_##GETTER(const ZXing_Barcode* barcode) { return TRANS(barcode->GETTER()); } | |
| 214 | |
| 215 ZX_GETTER(ZXing_BarcodeFormat, format, static_cast<ZXing_BarcodeFormat>) | |
| 216 ZX_GETTER(ZXing_ContentType, contentType, static_cast<ZXing_ContentType>) | |
| 217 ZX_GETTER(char*, text, copy) | |
| 218 ZX_GETTER(char*, ecLevel, copy) | |
| 219 ZX_GETTER(char*, symbologyIdentifier, copy) | |
| 220 ZX_GETTER(ZXing_Position, position, transmute_cast<ZXing_Position>) | |
| 221 | |
| 222 ZX_GETTER(int, orientation,) | |
| 223 ZX_GETTER(bool, hasECI,) | |
| 224 ZX_GETTER(bool, isInverted,) | |
| 225 ZX_GETTER(bool, isMirrored,) | |
| 226 ZX_GETTER(int, lineCount,) | |
| 227 | |
| 228 void ZXing_Barcode_delete(ZXing_Barcode* barcode) | |
| 229 { | |
| 230 delete barcode; | |
| 231 } | |
| 232 | |
| 233 void ZXing_Barcodes_delete(ZXing_Barcodes* barcodes) | |
| 234 { | |
| 235 if (barcodes != &emptyBarcodes) | |
| 236 delete barcodes; | |
| 237 } | |
| 238 | |
| 239 int ZXing_Barcodes_size(const ZXing_Barcodes* barcodes) | |
| 240 { | |
| 241 return barcodes ? Size(*barcodes) : 0; | |
| 242 } | |
| 243 | |
| 244 const ZXing_Barcode* ZXing_Barcodes_at(const ZXing_Barcodes* barcodes, int i) | |
| 245 { | |
| 246 if (!barcodes || i < 0 || i >= Size(*barcodes)) | |
| 247 return NULL; | |
| 248 return &(*barcodes)[i]; | |
| 249 } | |
| 250 | |
| 251 ZXing_Barcode* ZXing_Barcodes_move(ZXing_Barcodes* barcodes, int i) | |
| 252 { | |
| 253 if (!barcodes || i < 0 || i >= Size(*barcodes)) | |
| 254 return NULL; | |
| 255 | |
| 256 ZX_TRY(new Barcode(std::move((*barcodes)[i]))); | |
| 257 } | |
| 258 | |
| 259 /* | |
| 260 * ZXing/ReaderOptions.h | |
| 261 */ | |
| 262 | |
| 263 ZXing_ReaderOptions* ZXing_ReaderOptions_new() | |
| 264 { | |
| 265 ZX_TRY(new ReaderOptions()); | |
| 266 } | |
| 267 | |
| 268 void ZXing_ReaderOptions_delete(ZXing_ReaderOptions* opts) | |
| 269 { | |
| 270 delete opts; | |
| 271 } | |
| 272 | |
| 273 #define ZX_PROPERTY(TYPE, GETTER, SETTER) \ | |
| 274 TYPE ZXing_ReaderOptions_get##SETTER(const ZXing_ReaderOptions* opts) { return opts->GETTER(); } \ | |
| 275 void ZXing_ReaderOptions_set##SETTER(ZXing_ReaderOptions* opts, TYPE val) { opts->set##SETTER(val); } | |
| 276 | |
| 277 ZX_PROPERTY(bool, tryHarder, TryHarder) | |
| 278 ZX_PROPERTY(bool, tryRotate, TryRotate) | |
| 279 ZX_PROPERTY(bool, tryInvert, TryInvert) | |
| 280 ZX_PROPERTY(bool, tryDownscale, TryDownscale) | |
| 281 ZX_PROPERTY(bool, isPure, IsPure) | |
| 282 ZX_PROPERTY(bool, returnErrors, ReturnErrors) | |
| 283 ZX_PROPERTY(int, minLineCount, MinLineCount) | |
| 284 ZX_PROPERTY(int, maxNumberOfSymbols, MaxNumberOfSymbols) | |
| 285 | |
| 286 #undef ZX_PROPERTY | |
| 287 | |
| 288 void ZXing_ReaderOptions_setFormats(ZXing_ReaderOptions* opts, ZXing_BarcodeFormats formats) | |
| 289 { | |
| 290 opts->setFormats(static_cast<BarcodeFormat>(formats)); | |
| 291 } | |
| 292 | |
| 293 ZXing_BarcodeFormats ZXing_ReaderOptions_getFormats(const ZXing_ReaderOptions* opts) | |
| 294 { | |
| 295 auto v = opts->formats(); | |
| 296 return transmute_cast<ZXing_BarcodeFormats>(v); | |
| 297 } | |
| 298 | |
| 299 #define ZX_ENUM_PROPERTY(TYPE, GETTER, SETTER) \ | |
| 300 ZXing_##TYPE ZXing_ReaderOptions_get##SETTER(const ZXing_ReaderOptions* opts) { return static_cast<ZXing_##TYPE>(opts->GETTER()); } \ | |
| 301 void ZXing_ReaderOptions_set##SETTER(ZXing_ReaderOptions* opts, ZXing_##TYPE val) { opts->set##SETTER(static_cast<TYPE>(val)); } | |
| 302 | |
| 303 ZX_ENUM_PROPERTY(Binarizer, binarizer, Binarizer) | |
| 304 ZX_ENUM_PROPERTY(EanAddOnSymbol, eanAddOnSymbol, EanAddOnSymbol) | |
| 305 ZX_ENUM_PROPERTY(TextMode, textMode, TextMode) | |
| 306 | |
| 307 | |
| 308 /* | |
| 309 * ZXing/ReadBarcode.h | |
| 310 */ | |
| 311 | |
| 312 ZXing_Barcodes* ZXing_ReadBarcodes(const ZXing_ImageView* iv, const ZXing_ReaderOptions* opts) | |
| 313 { | |
| 314 ZX_CHECK(iv, "ImageView param is NULL") | |
| 315 try { | |
| 316 auto res = ReadBarcodes(*iv, opts ? *opts : ReaderOptions{}); | |
| 317 return res.empty() ? &emptyBarcodes : new Barcodes(std::move(res)); | |
| 318 } | |
| 319 ZX_CATCH(NULL); | |
| 320 } | |
| 321 | |
| 322 | |
| 323 #ifdef ZXING_EXPERIMENTAL_API | |
| 324 /* | |
| 325 * ZXing/WriteBarcode.h | |
| 326 */ | |
| 327 | |
| 328 ZXing_CreatorOptions* ZXing_CreatorOptions_new(ZXing_BarcodeFormat format) | |
| 329 { | |
| 330 ZX_TRY(new CreatorOptions(static_cast<BarcodeFormat>(format))); | |
| 331 } | |
| 332 | |
| 333 void ZXing_CreatorOptions_delete(ZXing_CreatorOptions* opts) | |
| 334 { | |
| 335 delete opts; | |
| 336 } | |
| 337 | |
| 338 #define ZX_PROPERTY(TYPE, GETTER, SETTER) \ | |
| 339 TYPE ZXing_CreatorOptions_get##SETTER(const ZXing_CreatorOptions* opts) { return opts->GETTER(); } \ | |
| 340 void ZXing_CreatorOptions_set##SETTER(ZXing_CreatorOptions* opts, TYPE val) { opts->GETTER(val); } | |
| 341 | |
| 342 ZX_PROPERTY(bool, readerInit, ReaderInit) | |
| 343 ZX_PROPERTY(bool, forceSquareDataMatrix, ForceSquareDataMatrix) | |
| 344 | |
| 345 #undef ZX_PROPERTY | |
| 346 | |
| 347 //ZX_PROPERTY(BarcodeFormat, format, Format) | |
| 348 | |
| 349 char* ZXing_CreatorOptions_getEcLevel(const ZXing_CreatorOptions* opts) | |
| 350 { | |
| 351 return copy(opts->ecLevel()); | |
| 352 } | |
| 353 | |
| 354 void ZXing_CreatorOptions_setEcLevel(ZXing_CreatorOptions* opts, const char* val) | |
| 355 { | |
| 356 opts->ecLevel(val); | |
| 357 } | |
| 358 | |
| 359 | |
| 360 ZXing_WriterOptions* ZXing_WriterOptions_new() | |
| 361 { | |
| 362 ZX_TRY(new ZXing_WriterOptions()); | |
| 363 } | |
| 364 | |
| 365 void ZXing_WriterOptions_delete(ZXing_WriterOptions* opts) | |
| 366 { | |
| 367 delete opts; | |
| 368 } | |
| 369 | |
| 370 #define ZX_PROPERTY(TYPE, GETTER, SETTER) \ | |
| 371 TYPE ZXing_WriterOptions_get##SETTER(const ZXing_WriterOptions* opts) { return opts->GETTER(); } \ | |
| 372 void ZXing_WriterOptions_set##SETTER(ZXing_WriterOptions* opts, TYPE val) { opts->GETTER(val); } | |
| 373 | |
| 374 ZX_PROPERTY(int, scale, Scale) | |
| 375 ZX_PROPERTY(int, sizeHint, SizeHint) | |
| 376 ZX_PROPERTY(int, rotate, Rotate) | |
| 377 ZX_PROPERTY(bool, withHRT, WithHRT) | |
| 378 ZX_PROPERTY(bool, withQuietZones, WithQuietZones) | |
| 379 | |
| 380 #undef ZX_PROPERTY | |
| 381 | |
| 382 ZXing_Barcode* ZXing_CreateBarcodeFromText(const char* data, int size, const ZXing_CreatorOptions* opts) | |
| 383 { | |
| 384 ZX_CHECK(data && opts, "Data and/or options param in CreateBarcodeFromText is NULL") | |
| 385 ZX_TRY(new Barcode(CreateBarcodeFromText({data, size ? static_cast<size_t>(size) : strlen(data)}, *opts));) | |
| 386 } | |
| 387 | |
| 388 ZXing_Barcode* ZXing_CreateBarcodeFromBytes(const void* data, int size, const ZXing_CreatorOptions* opts) | |
| 389 { | |
| 390 ZX_CHECK(data && size && opts, "Data and/or options param in CreateBarcodeFromBytes is NULL") | |
| 391 ZX_TRY(new Barcode(CreateBarcodeFromBytes(data, size, *opts))) | |
| 392 } | |
| 393 | |
| 394 char* ZXing_WriteBarcodeToSVG(const ZXing_Barcode* barcode, const ZXing_WriterOptions* opts) | |
| 395 { | |
| 396 ZX_CHECK(barcode, "Barcode param in WriteBarcodeToSVG is NULL") | |
| 397 ZX_TRY(copy(opts ? WriteBarcodeToSVG(*barcode, *opts) : WriteBarcodeToSVG(*barcode))) | |
| 398 } | |
| 399 | |
| 400 ZXing_Image* ZXing_WriteBarcodeToImage(const ZXing_Barcode* barcode, const ZXing_WriterOptions* opts) | |
| 401 { | |
| 402 ZX_CHECK(barcode, "Barcode param in WriteBarcodeToSVG is NULL") | |
| 403 ZX_TRY(new Image(opts ? WriteBarcodeToImage(*barcode, *opts) : WriteBarcodeToImage(*barcode))) | |
| 404 } | |
| 405 | |
| 406 #endif | |
| 407 | |
| 408 /* | |
| 409 * ZXingC.h | |
| 410 */ | |
| 411 | |
| 412 char* ZXing_LastErrorMsg() | |
| 413 { | |
| 414 if (lastErrorMsg.empty()) | |
| 415 return NULL; | |
| 416 | |
| 417 return copy(std::exchange(lastErrorMsg, {})); | |
| 418 } | |
| 419 | |
| 420 const char* ZXing_Version() | |
| 421 { | |
| 422 return ZXING_VERSION_STR; | |
| 423 } | |
| 424 | |
| 425 void ZXing_free(void* ptr) | |
| 426 { | |
| 427 if (ptr != ZXing_Version()) | |
| 428 free(ptr); | |
| 429 } | |
| 430 | |
| 431 } // extern "C" |
