Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend_qt/qzint.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 (C) 2008 by BogDan Vatra * | |
| 3 * bogdan@licentia.eu * | |
| 4 * Copyright (C) 2010-2024 Robin Stuart * | |
| 5 * * | |
| 6 * This program is free software: you can redistribute it and/or modify * | |
| 7 * it under the terms of the GNU General Public License as published by * | |
| 8 * the Free Software Foundation, either version 3 of the License, or * | |
| 9 * (at your option) any later version. * | |
| 10 * This program is distributed in the hope that it will be useful, * | |
| 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 13 * GNU General Public License for more details. * | |
| 14 * You should have received a copy of the GNU General Public License * | |
| 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 16 ***************************************************************************/ | |
| 17 /* SPDX-License-Identifier: GPL-3.0-or-later */ | |
| 18 | |
| 19 #ifdef _MSC_VER | |
| 20 #if _MSC_VER >= 1900 /* MSVC 2015 */ | |
| 21 #pragma warning(disable: 4996) /* function or variable may be unsafe */ | |
| 22 #endif | |
| 23 #endif | |
| 24 | |
| 25 //#include <QDebug> | |
| 26 #include <QFontDatabase> | |
| 27 #include <QFontMetrics> | |
| 28 /* The following include is necessary to compile with Qt 5.15 on Windows; Qt 5.7 did not require it */ | |
| 29 #include <QPainterPath> | |
| 30 #include <QRegularExpression> | |
| 31 | |
| 32 #include <math.h> | |
| 33 #include <stdio.h> | |
| 34 #include "qzint.h" | |
| 35 #include "../backend/fonts/normal_ttf.h" /* Arimo */ | |
| 36 #include "../backend/fonts/upcean_ttf.h" /* OCR-B subset (digits, "<", ">") */ | |
| 37 | |
| 38 // Shorthand | |
| 39 #define QSL QStringLiteral | |
| 40 #define QSEmpty QLatin1String("") | |
| 41 | |
| 42 namespace Zint { | |
| 43 static const int maxSegs = 256; | |
| 44 static const int maxCLISegs = 10; /* CLI restricted to 10 segments (including main data) */ | |
| 45 | |
| 46 /* Matches RGB(A) hex string or CMYK decimal "C,M,Y,K" percentage string */ | |
| 47 static const QString colorREstr( | |
| 48 QSL("^([0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?)|(((100|[0-9]{0,2}),){3}(100|[0-9]{0,2}))$")); | |
| 49 Q_GLOBAL_STATIC_WITH_ARGS(QRegularExpression, colorRE, (colorREstr)) | |
| 50 | |
| 51 static const QString normalFontFamily = QSL("Arimo"); /* Sans-serif metrically compatible with Arial */ | |
| 52 static const QString upceanFontFamily = QSL("OCRB"); /* Monospace OCR-B */ | |
| 53 static const QString fontFamilyError = QSL("Arimo"); | |
| 54 static const int fontSizeError = 14; /* Point size */ | |
| 55 | |
| 56 static int normalFontID = -2; /* Use -2 as `addApplicationFontFromData()` returns -1 on error */ | |
| 57 | |
| 58 /* Load Arimo from static array */ | |
| 59 static int loadNormalFont() { | |
| 60 static const QByteArray normalFontArray | |
| 61 = QByteArray::fromRawData((const char *) normal_ttf, sizeof(normal_ttf)); | |
| 62 | |
| 63 normalFontID = QFontDatabase::addApplicationFontFromData(normalFontArray); | |
| 64 return normalFontID; | |
| 65 } | |
| 66 | |
| 67 static int upceanFontID = -2; /* Use -2 as `addApplicationFontFromData()` returns -1 on error */ | |
| 68 | |
| 69 /* Load OCR-B EAN/UPC subset from static array */ | |
| 70 static int loadUpceanFont() { | |
| 71 static const QByteArray upceanFontArray | |
| 72 = QByteArray::fromRawData((const char *) upcean_ttf, sizeof(upcean_ttf)); | |
| 73 | |
| 74 upceanFontID = QFontDatabase::addApplicationFontFromData(upceanFontArray); | |
| 75 return upceanFontID; | |
| 76 } | |
| 77 | |
| 78 /* Helper to convert QColor to RGB(A) hex string */ | |
| 79 static QString qcolor_to_str(const QColor &color) { | |
| 80 if (color.alpha() == 0xFF) { | |
| 81 return QString::asprintf("%02X%02X%02X", color.red(), color.green(), color.blue()); | |
| 82 } | |
| 83 return QString::asprintf("%02X%02X%02X%02X", color.red(), color.green(), color.blue(), color.alpha()); | |
| 84 } | |
| 85 | |
| 86 /* Helper to convert RGB(A) hex string or CMYK decimal "C,M,Y,K" percentage string) to QColor */ | |
| 87 static QColor str_to_qcolor(const QString &text) { | |
| 88 QColor color; | |
| 89 int r, g, b, a; | |
| 90 if (text.contains(',')) { | |
| 91 int comma1 = text.indexOf(','); | |
| 92 int comma2 = text.indexOf(',', comma1 + 1); | |
| 93 int comma3 = text.indexOf(',', comma2 + 1); | |
| 94 int black = 100 - text.mid(comma3 + 1).toInt(); | |
| 95 int val = 100 - text.mid(0, comma1).toInt(); | |
| 96 r = (int) roundf((0xFF * val * black) / 10000.0f); | |
| 97 val = 100 - text.mid(comma1 + 1, comma2 - comma1 - 1).toInt(); | |
| 98 g = (int) roundf((0xFF * val * black) / 10000.0f); | |
| 99 val = 100 - text.mid(comma2 + 1, comma3 - comma2 - 1).toInt(); | |
| 100 b = (int) roundf((0xFF * val * black) / 10000.0f); | |
| 101 a = 0xFF; | |
| 102 } else { | |
| 103 r = text.mid(0, 2).toInt(nullptr, 16); | |
| 104 g = text.mid(2, 2).toInt(nullptr, 16); | |
| 105 b = text.mid(4, 2).toInt(nullptr, 16); | |
| 106 a = text.length() == 8 ? text.mid(6, 2).toInt(nullptr, 16) : 0xFF; | |
| 107 } | |
| 108 color.setRgb(r, g, b, a); | |
| 109 return color; | |
| 110 } | |
| 111 | |
| 112 /* Helper to convert ECI combo index to ECI value */ | |
| 113 static int ECIIndexToECI(const int ECIIndex) { | |
| 114 int ret; | |
| 115 if (ECIIndex >= 1 && ECIIndex <= 11) { | |
| 116 ret = ECIIndex + 2; | |
| 117 } else if (ECIIndex >= 12 && ECIIndex <= 15) { | |
| 118 ret = ECIIndex + 3; | |
| 119 } else if (ECIIndex >= 16 && ECIIndex <= 31) { | |
| 120 ret = ECIIndex + 4; | |
| 121 } else if (ECIIndex == 32) { | |
| 122 ret = 170; /* ISO 646 Invariant */ | |
| 123 } else if (ECIIndex == 33) { | |
| 124 ret = 899; /* 8-bit binary data */ | |
| 125 } else { | |
| 126 ret = 0; | |
| 127 } | |
| 128 return ret; | |
| 129 } | |
| 130 | |
| 131 /* Helper to calculate max right and bottom of elements for fudging `render()` */ | |
| 132 static void getMaxRectsRightBottom(struct zint_vector *vector, int &maxRight, int &maxBottom) { | |
| 133 struct zint_vector_rect *rect; | |
| 134 struct zint_vector_hexagon *hex; | |
| 135 struct zint_vector_circle *circle; | |
| 136 | |
| 137 maxRight = maxBottom = -1; | |
| 138 | |
| 139 for (rect = vector->rectangles; rect; rect = rect->next) { | |
| 140 if (rect->x + rect->width > maxRight) { | |
| 141 maxRight = rect->x + rect->width; | |
| 142 } | |
| 143 if (rect->y + rect->height > maxBottom) { | |
| 144 maxBottom = rect->y + rect->height; | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 for (hex = vector->hexagons; hex; hex = hex->next) { | |
| 149 if (hex->x + hex->diameter > maxRight) { | |
| 150 maxRight = hex->x + hex->diameter; | |
| 151 } | |
| 152 if (hex->y + hex->diameter > maxBottom) { | |
| 153 maxBottom = hex->y + hex->diameter; | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 for (circle = vector->circles; circle; circle = circle->next) { | |
| 158 if (circle->x + circle->diameter + circle->width > maxRight) { | |
| 159 maxRight = circle->x + circle->diameter + circle->width; | |
| 160 } | |
| 161 if (circle->y + circle->diameter + circle->width > maxBottom) { | |
| 162 maxBottom = circle->y + circle->diameter + circle->width; | |
| 163 } | |
| 164 } | |
| 165 | |
| 166 // TODO: Strings? | |
| 167 } | |
| 168 | |
| 169 /* Segment constructors */ | |
| 170 QZintSeg::QZintSeg() : m_eci(0) {} | |
| 171 QZintSeg::QZintSeg(const QString& text, const int ECIIndex) : m_text(text), m_eci(ECIIndexToECI(ECIIndex)) {} | |
| 172 | |
| 173 QZint::QZint() | |
| 174 : m_zintSymbol(nullptr), m_symbol(BARCODE_CODE128), m_input_mode(UNICODE_MODE), | |
| 175 m_height(0.0f), | |
| 176 m_option_1(-1), m_option_2(0), m_option_3(0), | |
| 177 m_dpmm(0.0f), | |
| 178 m_scale(1.0f), | |
| 179 m_dotty(false), m_dot_size(4.0f / 5.0f), | |
| 180 m_guardDescent(5.0f), | |
| 181 m_textGap(1.0f), | |
| 182 m_fgStr(QSL("000000")), m_bgStr(QSL("FFFFFF")), m_cmyk(false), | |
| 183 m_borderType(0), m_borderWidth(0), | |
| 184 m_whitespace(0), m_vwhitespace(0), | |
| 185 m_fontSetting(0), | |
| 186 m_show_hrt(true), | |
| 187 m_gssep(false), | |
| 188 m_quiet_zones(false), m_no_quiet_zones(false), | |
| 189 m_compliant_height(false), | |
| 190 m_rotate_angle(0), | |
| 191 m_eci(0), | |
| 192 m_gs1parens(false), m_gs1nocheck(false), | |
| 193 m_reader_init(false), | |
| 194 m_guard_whitespace(false), | |
| 195 m_embed_vector_font(false), | |
| 196 m_warn_level(WARN_DEFAULT), m_debug(false), | |
| 197 m_encodedWidth(0), m_encodedRows(0), m_encodedHeight(0.0f), | |
| 198 m_vectorWidth(0.0f), m_vectorHeight(0.0f), | |
| 199 m_error(0), | |
| 200 target_size_horiz(0), target_size_vert(0) // Legacy | |
| 201 { | |
| 202 memset(&m_structapp, 0, sizeof(m_structapp)); | |
| 203 } | |
| 204 | |
| 205 QZint::~QZint() { | |
| 206 if (m_zintSymbol) | |
| 207 ZBarcode_Delete(m_zintSymbol); | |
| 208 } | |
| 209 | |
| 210 bool QZint::resetSymbol() { | |
| 211 m_error = 0; | |
| 212 m_lastError.clear(); | |
| 213 | |
| 214 if (m_zintSymbol) { | |
| 215 ZBarcode_Reset(m_zintSymbol); | |
| 216 } else if (!(m_zintSymbol = ZBarcode_Create())) { | |
| 217 m_error = ZINT_ERROR_MEMORY; | |
| 218 m_lastError = QSL("Insufficient memory for Zint structure"); | |
| 219 return false; | |
| 220 } | |
| 221 | |
| 222 m_zintSymbol->symbology = m_symbol; | |
| 223 m_zintSymbol->height = m_height; | |
| 224 m_zintSymbol->scale = m_scale; | |
| 225 m_zintSymbol->whitespace_width = m_whitespace; | |
| 226 m_zintSymbol->whitespace_height = m_vwhitespace; | |
| 227 m_zintSymbol->border_width = m_borderWidth; | |
| 228 m_zintSymbol->output_options = m_borderType | m_fontSetting; | |
| 229 if (m_dotty) { | |
| 230 m_zintSymbol->output_options |= BARCODE_DOTTY_MODE; | |
| 231 } | |
| 232 if (m_cmyk) { | |
| 233 m_zintSymbol->output_options |= CMYK_COLOUR; | |
| 234 } | |
| 235 if (m_gssep) { | |
| 236 m_zintSymbol->output_options |= GS1_GS_SEPARATOR; | |
| 237 } | |
| 238 if (m_quiet_zones) { | |
| 239 m_zintSymbol->output_options |= BARCODE_QUIET_ZONES; | |
| 240 } | |
| 241 if (m_no_quiet_zones) { | |
| 242 m_zintSymbol->output_options |= BARCODE_NO_QUIET_ZONES; | |
| 243 } | |
| 244 if (m_compliant_height) { | |
| 245 m_zintSymbol->output_options |= COMPLIANT_HEIGHT; | |
| 246 } | |
| 247 if (m_reader_init) { | |
| 248 m_zintSymbol->output_options |= READER_INIT; | |
| 249 } | |
| 250 if (m_guard_whitespace) { | |
| 251 m_zintSymbol->output_options |= EANUPC_GUARD_WHITESPACE; | |
| 252 } | |
| 253 if (m_embed_vector_font) { | |
| 254 m_zintSymbol->output_options |= EMBED_VECTOR_FONT; | |
| 255 } | |
| 256 strcpy(m_zintSymbol->fgcolour, m_fgStr.toLatin1().left(15)); | |
| 257 strcpy(m_zintSymbol->bgcolour, m_bgStr.toLatin1().left(15)); | |
| 258 strcpy(m_zintSymbol->primary, m_primaryMessage.toLatin1().left(127)); | |
| 259 m_zintSymbol->option_1 = m_option_1; | |
| 260 m_zintSymbol->option_2 = m_option_2; | |
| 261 m_zintSymbol->option_3 = m_option_3; | |
| 262 m_zintSymbol->show_hrt = m_show_hrt ? 1 : 0; | |
| 263 m_zintSymbol->input_mode = m_input_mode; | |
| 264 if (m_gs1parens) { | |
| 265 m_zintSymbol->input_mode |= GS1PARENS_MODE; | |
| 266 } | |
| 267 if (m_gs1nocheck) { | |
| 268 m_zintSymbol->input_mode |= GS1NOCHECK_MODE; | |
| 269 } | |
| 270 m_zintSymbol->eci = m_eci; | |
| 271 m_zintSymbol->dpmm = m_dpmm; | |
| 272 m_zintSymbol->dot_size = m_dot_size; | |
| 273 m_zintSymbol->guard_descent = m_guardDescent; | |
| 274 m_zintSymbol->text_gap = m_textGap; | |
| 275 m_zintSymbol->structapp = m_structapp; | |
| 276 m_zintSymbol->warn_level = m_warn_level; | |
| 277 m_zintSymbol->debug = m_debug ? ZINT_DEBUG_PRINT : 0; | |
| 278 | |
| 279 return true; | |
| 280 } | |
| 281 | |
| 282 void QZint::encode() { | |
| 283 if (resetSymbol()) { | |
| 284 if (m_segs.empty()) { | |
| 285 QByteArray bstr = m_text.toUtf8(); | |
| 286 /* Note do our own rotation */ | |
| 287 m_error = ZBarcode_Encode_and_Buffer_Vector(m_zintSymbol, (unsigned char *) bstr.data(), | |
| 288 bstr.length(), 0); | |
| 289 } else { | |
| 290 struct zint_seg segs[maxSegs]; | |
| 291 std::vector<QByteArray> bstrs; | |
| 292 int seg_count = convertSegs(segs, bstrs); | |
| 293 /* Note do our own rotation */ | |
| 294 m_error = ZBarcode_Encode_Segs_and_Buffer_Vector(m_zintSymbol, segs, seg_count, 0); | |
| 295 } | |
| 296 m_lastError = m_zintSymbol->errtxt; | |
| 297 } | |
| 298 | |
| 299 if (m_error < ZINT_ERROR) { | |
| 300 m_borderType = m_zintSymbol->output_options & (BARCODE_BIND | BARCODE_BOX | BARCODE_BIND_TOP); | |
| 301 m_height = m_zintSymbol->height; | |
| 302 m_borderWidth = m_zintSymbol->border_width; | |
| 303 m_whitespace = m_zintSymbol->whitespace_width; | |
| 304 m_vwhitespace = m_zintSymbol->whitespace_height; | |
| 305 m_encodedWidth = m_zintSymbol->width; | |
| 306 m_encodedRows = m_zintSymbol->rows; | |
| 307 m_encodedHeight = m_zintSymbol->height; | |
| 308 m_vectorWidth = m_zintSymbol->vector->width; | |
| 309 m_vectorHeight = m_zintSymbol->vector->height; | |
| 310 emit encoded(); | |
| 311 } else { | |
| 312 m_encodedWidth = m_encodedRows = 0; | |
| 313 m_encodedHeight = m_vectorWidth = m_vectorHeight = 0.0f; | |
| 314 emit errored(); | |
| 315 } | |
| 316 } | |
| 317 | |
| 318 /* Symbology to use (see BARCODE_XXX) */ | |
| 319 int QZint::symbol() const { | |
| 320 return m_symbol; | |
| 321 } | |
| 322 | |
| 323 void QZint::setSymbol(int symbol) { | |
| 324 m_symbol = symbol; | |
| 325 } | |
| 326 | |
| 327 /* Input data encoding. Default UNICODE_MODE */ | |
| 328 int QZint::inputMode() const { | |
| 329 return m_input_mode; | |
| 330 } | |
| 331 | |
| 332 void QZint::setInputMode(int input_mode) { | |
| 333 m_input_mode = input_mode; | |
| 334 } | |
| 335 | |
| 336 /* Input data (segment 0 text) */ | |
| 337 QString QZint::text() const { | |
| 338 return m_text; | |
| 339 } | |
| 340 | |
| 341 /* Set input data. Note: clears segs */ | |
| 342 void QZint::setText(const QString& text) { | |
| 343 m_text = text; | |
| 344 m_segs.clear(); | |
| 345 } | |
| 346 | |
| 347 /* Input segments. */ | |
| 348 std::vector<QZintSeg> QZint::segs() const { | |
| 349 return m_segs; | |
| 350 } | |
| 351 | |
| 352 /* Set segments. Note: clears text and sets eci */ | |
| 353 void QZint::setSegs(const std::vector<QZintSeg>& segs) { | |
| 354 m_segs = segs; | |
| 355 m_text.clear(); | |
| 356 if (m_segs.size()) { /* Make sure `symbol->eci` synced */ | |
| 357 m_eci = m_segs[0].m_eci; | |
| 358 } | |
| 359 } | |
| 360 | |
| 361 /* Primary message (Maxicode, Composite) */ | |
| 362 QString QZint::primaryMessage() const { | |
| 363 return m_primaryMessage; | |
| 364 } | |
| 365 | |
| 366 void QZint::setPrimaryMessage(const QString& primaryMessage) { | |
| 367 m_primaryMessage = primaryMessage; | |
| 368 } | |
| 369 | |
| 370 /* Symbol height in X-dimensions */ | |
| 371 float QZint::height() const { | |
| 372 return m_height; | |
| 373 } | |
| 374 | |
| 375 void QZint::setHeight(float height) { | |
| 376 m_height = height; | |
| 377 } | |
| 378 | |
| 379 /* Symbol-specific options (see "../docs/manual.txt") */ | |
| 380 int QZint::option1() const { | |
| 381 return m_option_1; | |
| 382 } | |
| 383 | |
| 384 void QZint::setOption1(int option_1) { | |
| 385 m_option_1 = option_1; | |
| 386 } | |
| 387 | |
| 388 /* Symbol-specific options */ | |
| 389 int QZint::option2() const { | |
| 390 return m_option_2; | |
| 391 } | |
| 392 | |
| 393 void QZint::setOption2(int option) { | |
| 394 m_option_2 = option; | |
| 395 } | |
| 396 | |
| 397 int QZint::option3() const { | |
| 398 return m_option_3; | |
| 399 } | |
| 400 | |
| 401 void QZint::setOption3(int option) { | |
| 402 m_option_3 = option; | |
| 403 } | |
| 404 | |
| 405 /* Scale factor when printing barcode, i.e. adjusts X-dimension */ | |
| 406 float QZint::scale() const { | |
| 407 return m_scale; | |
| 408 } | |
| 409 | |
| 410 void QZint::setScale(float scale) { | |
| 411 m_scale = scale; | |
| 412 } | |
| 413 | |
| 414 /* Resolution of output in dots per mm (BMP/EMF/PCX/PNG/TIF only) */ | |
| 415 float QZint::dpmm() const { | |
| 416 return m_dpmm; | |
| 417 } | |
| 418 | |
| 419 void QZint::setDPMM(float dpmm) { | |
| 420 m_dpmm = dpmm; | |
| 421 } | |
| 422 | |
| 423 /* Dotty mode */ | |
| 424 bool QZint::dotty() const { | |
| 425 return m_dotty; | |
| 426 } | |
| 427 | |
| 428 void QZint::setDotty(bool dotty) { | |
| 429 m_dotty = dotty; | |
| 430 } | |
| 431 | |
| 432 /* Size of dots used in BARCODE_DOTTY_MODE */ | |
| 433 float QZint::dotSize() const { | |
| 434 return m_dot_size; | |
| 435 } | |
| 436 | |
| 437 void QZint::setDotSize(float dotSize) { | |
| 438 m_dot_size = dotSize; | |
| 439 } | |
| 440 | |
| 441 /* Height in X-dimensions that EAN/UPC guard bars descend */ | |
| 442 float QZint::guardDescent() const { | |
| 443 return m_guardDescent; | |
| 444 } | |
| 445 | |
| 446 void QZint::setGuardDescent(float guardDescent) { | |
| 447 m_guardDescent = guardDescent; | |
| 448 } | |
| 449 | |
| 450 /* Structured Append info */ | |
| 451 int QZint::structAppCount() const { | |
| 452 return m_structapp.count; | |
| 453 } | |
| 454 | |
| 455 int QZint::structAppIndex() const { | |
| 456 return m_structapp.index; | |
| 457 } | |
| 458 | |
| 459 QString QZint::structAppID() const { | |
| 460 return m_structapp.id; | |
| 461 } | |
| 462 | |
| 463 void QZint::setStructApp(const int count, const int index, const QString& id) { | |
| 464 if (count) { | |
| 465 m_structapp.count = count; | |
| 466 m_structapp.index = index; | |
| 467 memset(m_structapp.id, 0, sizeof(m_structapp.id)); | |
| 468 if (!id.isEmpty()) { | |
| 469 QByteArray idArr = id.toLatin1(); | |
| 470 #if defined(__GNUC__) && __GNUC__ >= 8 && !defined(__clang__) | |
| 471 #pragma GCC diagnostic push | |
| 472 #pragma GCC diagnostic ignored "-Wstringop-truncation" | |
| 473 #endif | |
| 474 strncpy(m_structapp.id, idArr, sizeof(m_structapp.id)); | |
| 475 #if defined(__GNUC__) && !defined(__clang__) | |
| 476 #pragma GCC diagnostic pop | |
| 477 #endif | |
| 478 } | |
| 479 } else { | |
| 480 clearStructApp(); | |
| 481 } | |
| 482 } | |
| 483 | |
| 484 void QZint::clearStructApp() { | |
| 485 memset(&m_structapp, 0, sizeof(m_structapp)); | |
| 486 } | |
| 487 | |
| 488 /* Foreground colour (may be RGB(A) hex string or CMYK decimal "C,M,Y,K" percentage string) */ | |
| 489 QString QZint::fgStr() const { | |
| 490 return m_fgStr; | |
| 491 } | |
| 492 | |
| 493 bool QZint::setFgStr(const QString& fgStr) { | |
| 494 if (fgStr.indexOf(*colorRE) == 0) { | |
| 495 m_fgStr = fgStr; | |
| 496 return true; | |
| 497 } | |
| 498 return false; | |
| 499 } | |
| 500 | |
| 501 /* Foreground colour as QColor */ | |
| 502 QColor QZint::fgColor() const { | |
| 503 return str_to_qcolor(m_fgStr); | |
| 504 } | |
| 505 | |
| 506 void QZint::setFgColor(const QColor& fgColor) { | |
| 507 m_fgStr = qcolor_to_str(fgColor); | |
| 508 } | |
| 509 | |
| 510 /* Background colour (may be RGB(A) hex string or CMYK decimal "C,M,Y,K" percentage string) */ | |
| 511 QString QZint::bgStr() const { | |
| 512 return m_bgStr; | |
| 513 } | |
| 514 | |
| 515 bool QZint::setBgStr(const QString& bgStr) { | |
| 516 if (bgStr.indexOf(*colorRE) == 0) { | |
| 517 m_bgStr = bgStr; | |
| 518 return true; | |
| 519 } | |
| 520 return false; | |
| 521 } | |
| 522 | |
| 523 /* Background colour as QColor */ | |
| 524 QColor QZint::bgColor() const { | |
| 525 return str_to_qcolor(m_bgStr); | |
| 526 } | |
| 527 | |
| 528 void QZint::setBgColor(const QColor& bgColor) { | |
| 529 m_bgStr = qcolor_to_str(bgColor); | |
| 530 } | |
| 531 | |
| 532 /* Use CMYK colour space (Encapsulated PostScript and TIF) */ | |
| 533 bool QZint::cmyk() const { | |
| 534 return m_cmyk; | |
| 535 } | |
| 536 | |
| 537 void QZint::setCMYK(bool cmyk) { | |
| 538 m_cmyk = cmyk; | |
| 539 } | |
| 540 | |
| 541 /* Type of border above/below/around barcode */ | |
| 542 int QZint::borderType() const { | |
| 543 return m_borderType; | |
| 544 } | |
| 545 | |
| 546 void QZint::setBorderType(int borderTypeIndex) { | |
| 547 if (borderTypeIndex == 1) { | |
| 548 m_borderType = BARCODE_BIND; | |
| 549 } else if (borderTypeIndex == 2) { | |
| 550 m_borderType = BARCODE_BOX; | |
| 551 } else if (borderTypeIndex == 3) { | |
| 552 m_borderType = BARCODE_BIND_TOP; | |
| 553 } else { | |
| 554 m_borderType = 0; | |
| 555 } | |
| 556 } | |
| 557 | |
| 558 /* Size of border in X-dimensions */ | |
| 559 int QZint::borderWidth() const { | |
| 560 return m_borderWidth; | |
| 561 } | |
| 562 | |
| 563 void QZint::setBorderWidth(int borderWidth) { | |
| 564 if (borderWidth < 0 || borderWidth > 16) | |
| 565 borderWidth = 0; | |
| 566 m_borderWidth = borderWidth; | |
| 567 } | |
| 568 | |
| 569 /* Width in X-dimensions of whitespace to left & right of barcode */ | |
| 570 int QZint::whitespace() const { | |
| 571 return m_whitespace; | |
| 572 } | |
| 573 | |
| 574 void QZint::setWhitespace(int whitespace) { | |
| 575 m_whitespace = whitespace; | |
| 576 } | |
| 577 | |
| 578 /* Height in X-dimensions of whitespace above & below the barcode */ | |
| 579 int QZint::vWhitespace() const { | |
| 580 return m_vwhitespace; | |
| 581 } | |
| 582 | |
| 583 void QZint::setVWhitespace(int vWhitespace) { | |
| 584 m_vwhitespace = vWhitespace; | |
| 585 } | |
| 586 | |
| 587 /* Type of font to use i.e. normal, small, bold or (vector only) small bold */ | |
| 588 int QZint::fontSetting() const { | |
| 589 return m_fontSetting; | |
| 590 } | |
| 591 | |
| 592 void QZint::setFontSetting(int fontSettingIndex) { // Sets from comboBox index | |
| 593 if (fontSettingIndex == 1) { | |
| 594 m_fontSetting = BOLD_TEXT; | |
| 595 } else if (fontSettingIndex == 2) { | |
| 596 m_fontSetting = SMALL_TEXT; | |
| 597 } else if (fontSettingIndex == 3) { | |
| 598 m_fontSetting = SMALL_TEXT | BOLD_TEXT; | |
| 599 } else { | |
| 600 m_fontSetting = 0; | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 void QZint::setFontSettingValue(int fontSetting) { // Sets literal value | |
| 605 if ((fontSetting & (BOLD_TEXT | SMALL_TEXT)) == fontSetting) { | |
| 606 m_fontSetting = fontSetting; | |
| 607 } else { | |
| 608 m_fontSetting = 0; | |
| 609 } | |
| 610 } | |
| 611 | |
| 612 /* Text gap */ | |
| 613 float QZint::textGap() const { | |
| 614 return m_textGap; | |
| 615 } | |
| 616 | |
| 617 void QZint::setTextGap(float textGap) { | |
| 618 m_textGap = textGap; | |
| 619 } | |
| 620 | |
| 621 /* Show (true) or hide (false) Human Readable Text (HRT) */ | |
| 622 bool QZint::showText() const { | |
| 623 return m_show_hrt; | |
| 624 } | |
| 625 | |
| 626 void QZint::setShowText(bool showText) { | |
| 627 m_show_hrt = showText; | |
| 628 } | |
| 629 | |
| 630 /* Set to true to use GS (Group Separator) instead of FNC1 as GS1 separator (Data Matrix) */ | |
| 631 bool QZint::gsSep() const { | |
| 632 return m_gssep; | |
| 633 } | |
| 634 | |
| 635 void QZint::setGSSep(bool gsSep) { | |
| 636 m_gssep = gsSep; | |
| 637 } | |
| 638 | |
| 639 /* Add compliant quiet zones (additional to any specified whitespace) | |
| 640 Note: CODE16K, CODE49, CODABLOCKF, ITF14, EAN/UPC have default quiet zones */ | |
| 641 bool QZint::quietZones() const { | |
| 642 return m_quiet_zones; | |
| 643 } | |
| 644 | |
| 645 void QZint::setQuietZones(bool quietZones) { | |
| 646 m_quiet_zones = quietZones; | |
| 647 } | |
| 648 | |
| 649 /* Disable quiet zones, notably those with defaults as listed above */ | |
| 650 bool QZint::noQuietZones() const { | |
| 651 return m_no_quiet_zones; | |
| 652 } | |
| 653 | |
| 654 void QZint::setNoQuietZones(bool noQuietZones) { | |
| 655 m_no_quiet_zones = noQuietZones; | |
| 656 } | |
| 657 | |
| 658 /* Warn if height not compliant and use standard height (if any) as default */ | |
| 659 bool QZint::compliantHeight() const { | |
| 660 return m_compliant_height; | |
| 661 } | |
| 662 | |
| 663 void QZint::setCompliantHeight(bool compliantHeight) { | |
| 664 m_compliant_height = compliantHeight; | |
| 665 } | |
| 666 | |
| 667 /* Rotate barcode by angle (degrees 0, 90, 180 and 270) */ | |
| 668 int QZint::rotateAngle() const { | |
| 669 return m_rotate_angle; | |
| 670 } | |
| 671 | |
| 672 void QZint::setRotateAngle(int rotateIndex) { // Sets from comboBox index | |
| 673 if (rotateIndex == 1) { | |
| 674 m_rotate_angle = 90; | |
| 675 } else if (rotateIndex == 2) { | |
| 676 m_rotate_angle = 180; | |
| 677 } else if (rotateIndex == 3) { | |
| 678 m_rotate_angle = 270; | |
| 679 } else { | |
| 680 m_rotate_angle = 0; | |
| 681 } | |
| 682 } | |
| 683 | |
| 684 void QZint::setRotateAngleValue(int rotateAngle) { // Sets literal value | |
| 685 if (rotateAngle == 90) { | |
| 686 m_rotate_angle = 90; | |
| 687 } else if (rotateAngle == 180) { | |
| 688 m_rotate_angle = 180; | |
| 689 } else if (rotateAngle == 270) { | |
| 690 m_rotate_angle = 270; | |
| 691 } else { | |
| 692 m_rotate_angle = 0; | |
| 693 } | |
| 694 } | |
| 695 | |
| 696 /* Extended Channel Interpretation (segment 0 eci) */ | |
| 697 int QZint::eci() const { | |
| 698 return m_eci; | |
| 699 } | |
| 700 | |
| 701 void QZint::setECI(int ECIIndex) { // Sets from comboBox index | |
| 702 m_eci = ECIIndexToECI(ECIIndex); | |
| 703 } | |
| 704 | |
| 705 void QZint::setECIValue(int eci) { // Sets literal value | |
| 706 if (eci < 3 || (eci > 35 && eci != 170 && eci != 899) || eci == 14 || eci == 19) { | |
| 707 m_eci = 0; | |
| 708 } else { | |
| 709 m_eci = eci; | |
| 710 } | |
| 711 } | |
| 712 | |
| 713 /* Process parentheses as GS1 AI delimiters (instead of square brackets) */ | |
| 714 bool QZint::gs1Parens() const { | |
| 715 return m_gs1parens; | |
| 716 } | |
| 717 | |
| 718 void QZint::setGS1Parens(bool gs1Parens) { | |
| 719 m_gs1parens = gs1Parens; | |
| 720 } | |
| 721 | |
| 722 /* Do not check validity of GS1 data (except that printable ASCII only) */ | |
| 723 bool QZint::gs1NoCheck() const { | |
| 724 return m_gs1nocheck; | |
| 725 } | |
| 726 | |
| 727 void QZint::setGS1NoCheck(bool gs1NoCheck) { | |
| 728 m_gs1nocheck = gs1NoCheck; | |
| 729 } | |
| 730 | |
| 731 /* Reader Initialisation (Programming) */ | |
| 732 bool QZint::readerInit() const { | |
| 733 return m_reader_init; | |
| 734 } | |
| 735 | |
| 736 void QZint::setReaderInit(bool readerInit) { | |
| 737 m_reader_init = readerInit; | |
| 738 } | |
| 739 | |
| 740 /* Whether to add quiet zone indicators ("<", ">") to HRT (EAN/UPC) */ | |
| 741 bool QZint::guardWhitespace() const { | |
| 742 return m_guard_whitespace; | |
| 743 } | |
| 744 | |
| 745 void QZint::setGuardWhitespace(bool guardWhitespace) { | |
| 746 m_guard_whitespace = guardWhitespace; | |
| 747 } | |
| 748 | |
| 749 /* Whether to embed the font in vector output - currently only for SVG output of EAN/UPC */ | |
| 750 bool QZint::embedVectorFont() const { | |
| 751 return m_embed_vector_font; | |
| 752 } | |
| 753 | |
| 754 void QZint::setEmbedVectorFont(bool embedVectorFont) { | |
| 755 m_embed_vector_font = embedVectorFont; | |
| 756 } | |
| 757 | |
| 758 /* Affects error/warning value returned by Zint API (see `getError()` below) */ | |
| 759 int QZint::warnLevel() const { | |
| 760 return m_warn_level; | |
| 761 } | |
| 762 | |
| 763 void QZint::setWarnLevel(int warnLevel) { | |
| 764 m_warn_level = warnLevel; | |
| 765 } | |
| 766 | |
| 767 /* Debugging flags */ | |
| 768 bool QZint::debug() const { | |
| 769 return m_debug; | |
| 770 } | |
| 771 | |
| 772 void QZint::setDebug(bool debug) { | |
| 773 m_debug = debug; | |
| 774 } | |
| 775 | |
| 776 /* Symbol output info set by Zint on successful `render()` */ | |
| 777 int QZint::encodedWidth() const { // Read-only, encoded width (no. of modules encoded) | |
| 778 return m_encodedWidth; | |
| 779 } | |
| 780 | |
| 781 int QZint::encodedRows() const { // Read-only, no. of rows encoded | |
| 782 return m_encodedRows; | |
| 783 } | |
| 784 | |
| 785 float QZint::encodedHeight() const { // Read-only, in X-dimensions | |
| 786 if (m_symbol == BARCODE_MAXICODE) { // Maxicode encoded height is meaningless, so return fixed value | |
| 787 return 33 * 0.866f; // √3 / 2 | |
| 788 } | |
| 789 return m_encodedHeight; | |
| 790 } | |
| 791 | |
| 792 float QZint::vectorWidth() const { // Read-only, scaled width | |
| 793 return m_vectorWidth; | |
| 794 } | |
| 795 | |
| 796 float QZint::vectorHeight() const { // Read-only, scaled height | |
| 797 return m_vectorHeight; | |
| 798 } | |
| 799 | |
| 800 /* Legacy property getters/setters */ | |
| 801 void QZint::setWidth(int width) { setOption2(width); } | |
| 802 int QZint::width() const { return m_option_2; } | |
| 803 void QZint::setSecurityLevel(int securityLevel) { setOption1(securityLevel); } | |
| 804 int QZint::securityLevel() const { return m_option_1; } | |
| 805 void QZint::setPdf417CodeWords(int /*pdf417CodeWords*/) {} | |
| 806 int QZint::pdf417CodeWords() const { return 0; } | |
| 807 void QZint::setHideText(bool hide) { setShowText(!hide); } | |
| 808 void QZint::setTargetSize(int width, int height) { | |
| 809 target_size_horiz = width; | |
| 810 target_size_vert = height; | |
| 811 } | |
| 812 QString QZint::error_message() const { return m_lastError; } /* Same as lastError() */ | |
| 813 | |
| 814 /* Test capabilities - `ZBarcode_Cap()` */ | |
| 815 bool QZint::hasHRT(int symbology) const { | |
| 816 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_HRT); | |
| 817 } | |
| 818 | |
| 819 bool QZint::isStackable(int symbology) const { | |
| 820 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_STACKABLE); | |
| 821 } | |
| 822 | |
| 823 bool QZint::isEANUPC(int symbology) const { | |
| 824 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_EANUPC); | |
| 825 } | |
| 826 | |
| 827 bool QZint::isExtendable(int symbology) const { /* Legacy - same as `isEANUPC()` */ | |
| 828 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_EANUPC); | |
| 829 } | |
| 830 | |
| 831 bool QZint::isComposite(int symbology) const { | |
| 832 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_COMPOSITE); | |
| 833 } | |
| 834 | |
| 835 bool QZint::supportsECI(int symbology) const { | |
| 836 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_ECI); | |
| 837 } | |
| 838 | |
| 839 bool QZint::supportsGS1(int symbology) const { | |
| 840 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_GS1); | |
| 841 } | |
| 842 | |
| 843 bool QZint::isDotty(int symbology) const { | |
| 844 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_DOTTY); | |
| 845 } | |
| 846 | |
| 847 bool QZint::hasDefaultQuietZones(int symbology) const { | |
| 848 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_QUIET_ZONES); | |
| 849 } | |
| 850 | |
| 851 bool QZint::isFixedRatio(int symbology) const { | |
| 852 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_FIXED_RATIO); | |
| 853 } | |
| 854 | |
| 855 bool QZint::supportsReaderInit(int symbology) const { | |
| 856 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_READER_INIT); | |
| 857 } | |
| 858 | |
| 859 bool QZint::supportsFullMultibyte(int symbology) const { | |
| 860 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_FULL_MULTIBYTE); | |
| 861 } | |
| 862 | |
| 863 bool QZint::hasMask(int symbology) const { | |
| 864 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_MASK); | |
| 865 } | |
| 866 | |
| 867 bool QZint::supportsStructApp(int symbology) const { | |
| 868 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_STRUCTAPP); | |
| 869 } | |
| 870 | |
| 871 bool QZint::hasCompliantHeight(int symbology) const { | |
| 872 return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_COMPLIANT_HEIGHT); | |
| 873 } | |
| 874 | |
| 875 /* Whether takes GS1 AI-delimited data */ | |
| 876 bool QZint::takesGS1AIData(int symbology) const { | |
| 877 if (symbology == 0) { | |
| 878 symbology = m_symbol; | |
| 879 } | |
| 880 switch (symbology) { | |
| 881 case BARCODE_GS1_128: | |
| 882 case BARCODE_DBAR_EXP: | |
| 883 case BARCODE_DBAR_EXPSTK: | |
| 884 return true; | |
| 885 break; | |
| 886 default: | |
| 887 return symbology >= BARCODE_EANX_CC && symbology <= BARCODE_DBAR_EXPSTK_CC; | |
| 888 break; | |
| 889 } | |
| 890 } | |
| 891 | |
| 892 /* Error or warning returned by Zint on `render()` or `save_to_file()` */ | |
| 893 int QZint::getError() const { | |
| 894 return m_error; | |
| 895 } | |
| 896 | |
| 897 /* Error message returned by Zint on `render()` or `save_to_file()` */ | |
| 898 const QString& QZint::lastError() const { | |
| 899 return m_lastError; | |
| 900 } | |
| 901 | |
| 902 /* Whether `lastError()` set */ | |
| 903 bool QZint::hasErrors() const { | |
| 904 return m_lastError.length(); | |
| 905 } | |
| 906 | |
| 907 bool QZint::save_to_file(const QString& filename) { | |
| 908 if (resetSymbol()) { | |
| 909 strcpy(m_zintSymbol->outfile, filename.toUtf8().left(255)); | |
| 910 if (m_segs.empty()) { | |
| 911 QByteArray bstr = m_text.toUtf8(); | |
| 912 m_error = ZBarcode_Encode_and_Print(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), | |
| 913 m_rotate_angle); | |
| 914 } else { | |
| 915 struct zint_seg segs[maxSegs]; | |
| 916 std::vector<QByteArray> bstrs; | |
| 917 int seg_count = convertSegs(segs, bstrs); | |
| 918 m_error = ZBarcode_Encode_Segs_and_Print(m_zintSymbol, segs, seg_count, m_rotate_angle); | |
| 919 } | |
| 920 } | |
| 921 if (m_error >= ZINT_ERROR) { | |
| 922 m_lastError = m_zintSymbol->errtxt; | |
| 923 m_encodedWidth = m_encodedRows = 0; | |
| 924 m_encodedHeight = m_vectorWidth = m_vectorHeight = 0.0f; | |
| 925 emit errored(); | |
| 926 return false; | |
| 927 } | |
| 928 return true; | |
| 929 } | |
| 930 | |
| 931 /* Convert `zint_vector_rect->colour` to Qt color */ | |
| 932 Qt::GlobalColor QZint::colourToQtColor(int colour) { | |
| 933 switch (colour) { | |
| 934 case 1: // Cyan | |
| 935 return Qt::cyan; | |
| 936 break; | |
| 937 case 2: // Blue | |
| 938 return Qt::blue; | |
| 939 break; | |
| 940 case 3: // Magenta | |
| 941 return Qt::magenta; | |
| 942 break; | |
| 943 case 4: // Red | |
| 944 return Qt::red; | |
| 945 break; | |
| 946 case 5: // Yellow | |
| 947 return Qt::yellow; | |
| 948 break; | |
| 949 case 6: // Green | |
| 950 return Qt::green; | |
| 951 break; | |
| 952 case 8: // White | |
| 953 return Qt::white; | |
| 954 break; | |
| 955 default: | |
| 956 return Qt::black; | |
| 957 break; | |
| 958 } | |
| 959 } | |
| 960 | |
| 961 /* Helper to convert `m_segs` to `struct zint_seg[]` */ | |
| 962 int QZint::convertSegs(struct zint_seg segs[], std::vector<QByteArray>& bstrs) { | |
| 963 bstrs.reserve(m_segs.size()); | |
| 964 int i; | |
| 965 for (i = 0; i < (int) m_segs.size() && i < maxSegs && !m_segs[i].m_text.isEmpty(); i++) { | |
| 966 segs[i].eci = m_segs[i].m_eci; | |
| 967 bstrs.push_back(m_segs[i].m_text.toUtf8()); | |
| 968 segs[i].source = (unsigned char *) bstrs.back().data(); | |
| 969 segs[i].length = bstrs.back().length(); | |
| 970 } | |
| 971 return i; | |
| 972 } | |
| 973 | |
| 974 /* Encode and display barcode in `paintRect` using `painter`. | |
| 975 Note: legacy argument `mode` is not used */ | |
| 976 void QZint::render(QPainter& painter, const QRectF& paintRect, AspectRatioMode /*mode*/) { | |
| 977 struct zint_vector_rect *rect; | |
| 978 struct zint_vector_hexagon *hex; | |
| 979 struct zint_vector_circle *circle; | |
| 980 struct zint_vector_string *string; | |
| 981 QColor fgColor = str_to_qcolor(m_fgStr); | |
| 982 QColor bgColor = str_to_qcolor(m_bgStr); | |
| 983 encode(); | |
| 984 | |
| 985 painter.save(); | |
| 986 | |
| 987 if (m_error >= ZINT_ERROR) { | |
| 988 painter.setRenderHint(QPainter::Antialiasing); | |
| 989 QFont font(fontFamilyError, fontSizeError); | |
| 990 painter.setFont(font); | |
| 991 painter.drawText(paintRect, Qt::AlignCenter | Qt::TextWordWrap, m_lastError); | |
| 992 painter.restore(); | |
| 993 return; | |
| 994 } | |
| 995 | |
| 996 painter.setClipRect(paintRect, Qt::IntersectClip); | |
| 997 | |
| 998 qreal xtr = paintRect.x(); | |
| 999 qreal ytr = paintRect.y(); | |
| 1000 qreal scale; | |
| 1001 | |
| 1002 qreal gwidth = m_zintSymbol->vector->width; | |
| 1003 qreal gheight = m_zintSymbol->vector->height; | |
| 1004 | |
| 1005 if (m_rotate_angle == 90 || m_rotate_angle == 270) { | |
| 1006 if (paintRect.width() / gheight < paintRect.height() / gwidth) { | |
| 1007 scale = paintRect.width() / gheight; | |
| 1008 } else { | |
| 1009 scale = paintRect.height() / gwidth; | |
| 1010 } | |
| 1011 } else { | |
| 1012 if (paintRect.width() / gwidth < paintRect.height() / gheight) { | |
| 1013 scale = paintRect.width() / gwidth; | |
| 1014 } else { | |
| 1015 scale = paintRect.height() / gheight; | |
| 1016 } | |
| 1017 } | |
| 1018 | |
| 1019 xtr += (qreal) (paintRect.width() - gwidth * scale) / 2.0; | |
| 1020 ytr += (qreal) (paintRect.height() - gheight * scale) / 2.0; | |
| 1021 | |
| 1022 if (m_rotate_angle) { | |
| 1023 painter.translate(paintRect.width() / 2.0, paintRect.height() / 2.0); // Need to rotate around centre | |
| 1024 painter.rotate(m_rotate_angle); | |
| 1025 painter.translate(-paintRect.width() / 2.0, -paintRect.height() / 2.0); // Undo | |
| 1026 } | |
| 1027 | |
| 1028 painter.translate(xtr, ytr); | |
| 1029 painter.scale(scale, scale); | |
| 1030 | |
| 1031 QBrush bgBrush(bgColor); | |
| 1032 if (bgColor.alpha() != 0) { | |
| 1033 painter.fillRect(QRectF(0, 0, gwidth, gheight), bgBrush); | |
| 1034 } | |
| 1035 | |
| 1036 // Plot rectangles | |
| 1037 rect = m_zintSymbol->vector->rectangles; | |
| 1038 if (rect) { | |
| 1039 int maxRight = -1, maxBottom = -1; // Used for fudging below | |
| 1040 getMaxRectsRightBottom(m_zintSymbol->vector, maxRight, maxBottom); | |
| 1041 QBrush brush(Qt::SolidPattern); | |
| 1042 while (rect) { | |
| 1043 if (rect->colour == -1) { | |
| 1044 brush.setColor(fgColor); | |
| 1045 } else { | |
| 1046 brush.setColor(colourToQtColor(rect->colour)); | |
| 1047 } | |
| 1048 // Allow for rounding errors on translation/scaling TODO: proper calc | |
| 1049 float fudgeW = rect->x + rect->width == maxRight ? 0.1f : 0.0f; | |
| 1050 float fudgeH = rect->y + rect->height == maxBottom ? 0.1f : 0.0f; | |
| 1051 painter.fillRect(QRectF(rect->x, rect->y, rect->width + fudgeW, rect->height + fudgeH), brush); | |
| 1052 rect = rect->next; | |
| 1053 } | |
| 1054 } | |
| 1055 | |
| 1056 // Plot hexagons | |
| 1057 hex = m_zintSymbol->vector->hexagons; | |
| 1058 if (hex) { | |
| 1059 painter.setRenderHint(QPainter::Antialiasing); | |
| 1060 QBrush fgBrush(fgColor); | |
| 1061 qreal previous_diameter = 0.0, radius = 0.0, half_radius = 0.0, half_sqrt3_radius = 0.0; | |
| 1062 while (hex) { | |
| 1063 if (previous_diameter != hex->diameter) { | |
| 1064 previous_diameter = hex->diameter; | |
| 1065 radius = 0.5 * previous_diameter; | |
| 1066 half_radius = 0.25 * previous_diameter; | |
| 1067 half_sqrt3_radius = 0.43301270189221932338 * previous_diameter; | |
| 1068 } | |
| 1069 | |
| 1070 QPainterPath pt; | |
| 1071 pt.moveTo(hex->x, hex->y + radius); | |
| 1072 pt.lineTo(hex->x + half_sqrt3_radius, hex->y + half_radius); | |
| 1073 pt.lineTo(hex->x + half_sqrt3_radius, hex->y - half_radius); | |
| 1074 pt.lineTo(hex->x, hex->y - radius); | |
| 1075 pt.lineTo(hex->x - half_sqrt3_radius, hex->y - half_radius); | |
| 1076 pt.lineTo(hex->x - half_sqrt3_radius, hex->y + half_radius); | |
| 1077 pt.lineTo(hex->x, hex->y + radius); | |
| 1078 painter.fillPath(pt, fgBrush); | |
| 1079 | |
| 1080 hex = hex->next; | |
| 1081 } | |
| 1082 } | |
| 1083 | |
| 1084 // Plot dots (circles) | |
| 1085 circle = m_zintSymbol->vector->circles; | |
| 1086 if (circle) { | |
| 1087 painter.setRenderHint(QPainter::Antialiasing); | |
| 1088 QPen p; | |
| 1089 QBrush fgBrush(fgColor); | |
| 1090 qreal previous_diameter = 0.0, radius = 0.0; | |
| 1091 while (circle) { | |
| 1092 if (previous_diameter != circle->diameter) { | |
| 1093 previous_diameter = circle->diameter; | |
| 1094 radius = 0.5 * previous_diameter; | |
| 1095 } | |
| 1096 if (circle->colour) { // Set means use background colour (legacy, no longer used) | |
| 1097 p.setColor(bgColor); | |
| 1098 p.setWidthF(circle->width); | |
| 1099 painter.setPen(p); | |
| 1100 painter.setBrush(circle->width ? Qt::NoBrush : bgBrush); | |
| 1101 } else { | |
| 1102 p.setColor(fgColor); | |
| 1103 p.setWidthF(circle->width); | |
| 1104 painter.setPen(p); | |
| 1105 painter.setBrush(circle->width ? Qt::NoBrush : fgBrush); | |
| 1106 } | |
| 1107 painter.drawEllipse(QPointF(circle->x, circle->y), radius, radius); | |
| 1108 circle = circle->next; | |
| 1109 } | |
| 1110 } | |
| 1111 | |
| 1112 // Plot text | |
| 1113 string = m_zintSymbol->vector->strings; | |
| 1114 if (string) { | |
| 1115 if (normalFontID == -2) { /* First time? */ | |
| 1116 loadNormalFont(); | |
| 1117 } | |
| 1118 if (upceanFontID == -2) { /* First time? */ | |
| 1119 loadUpceanFont(); | |
| 1120 } | |
| 1121 painter.setRenderHint(QPainter::Antialiasing); | |
| 1122 QPen p; | |
| 1123 p.setColor(fgColor); | |
| 1124 painter.setPen(p); | |
| 1125 bool bold = (m_zintSymbol->output_options & BOLD_TEXT) && !isEANUPC(); | |
| 1126 QFont font(isEANUPC() ? upceanFontFamily : normalFontFamily, -1 /*pointSize*/, | |
| 1127 bold ? QFont::Bold : -1); | |
| 1128 while (string) { | |
| 1129 font.setPixelSize(string->fsize); | |
| 1130 painter.setFont(font); | |
| 1131 QString content = QString::fromUtf8((const char *) string->text); | |
| 1132 /* string->y is baseline of font */ | |
| 1133 if (string->halign == 1) { /* Left align */ | |
| 1134 painter.drawText(QPointF(string->x, string->y), content); | |
| 1135 } else { | |
| 1136 QFontMetrics fm(painter.fontMetrics()); | |
| 1137 int width = fm.horizontalAdvance(content); | |
| 1138 if (string->halign == 2) { /* Right align */ | |
| 1139 painter.drawText(QPointF(string->x - width, string->y), content); | |
| 1140 } else { /* Centre align */ | |
| 1141 painter.drawText(QPointF(string->x - (width / 2.0), string->y), content); | |
| 1142 } | |
| 1143 } | |
| 1144 string = string->next; | |
| 1145 } | |
| 1146 } | |
| 1147 | |
| 1148 painter.restore(); | |
| 1149 } | |
| 1150 | |
| 1151 /* Returns the default X-dimension (`ZBarcode_Default_Xdim()`). | |
| 1152 If `symbology` non-zero then used instead of `symbol()` */ | |
| 1153 float QZint::defaultXdim(int symbology) const { | |
| 1154 return ZBarcode_Default_Xdim(symbology ? symbology : m_symbol); | |
| 1155 } | |
| 1156 | |
| 1157 /* Returns the scale to use for X-dimension `x_dim_mm` at `dpmm` for `filetype`. | |
| 1158 If `symbology` non-zero then used instead of `symbol()` */ | |
| 1159 float QZint::getScaleFromXdimDp(float x_dim_mm, float dpmm, const QString& fileType, int symbology) const { | |
| 1160 return ZBarcode_Scale_From_XdimDp(symbology ? symbology : m_symbol, x_dim_mm, dpmm, fileType.toLatin1()); | |
| 1161 } | |
| 1162 | |
| 1163 /* Reverse of `getScaleFromXdimDp()` above, returning the X-dimension or dot density given the scale `scale`. | |
| 1164 If `symbology` non-zero then used instead of `symbol()` */ | |
| 1165 float QZint::getXdimDpFromScale(float scale, float x_dim_mm_or_dpmm, const QString& fileType, | |
| 1166 int symbology) const { | |
| 1167 return ZBarcode_XdimDp_From_Scale(symbology ? symbology : m_symbol, scale, x_dim_mm_or_dpmm, | |
| 1168 fileType.toLatin1()); | |
| 1169 } | |
| 1170 | |
| 1171 /* Set `width_x_dim` and `height_x_dim` with estimated size of barcode based on X-dimension `x_dim`. To be called | |
| 1172 after a successful `render()`. Returns false if `scale()` zero or render is in error, otherwise true */ | |
| 1173 bool QZint::getWidthHeightXdim(float x_dim, float &width_x_dim, float &height_x_dim) const { | |
| 1174 | |
| 1175 if (m_scale == 0.0f || m_vectorWidth == 0.0f || m_vectorHeight == 0.0f) { | |
| 1176 width_x_dim = height_x_dim = 0.0f; | |
| 1177 return false; | |
| 1178 } | |
| 1179 | |
| 1180 const float scale = m_scale * 2.0f; | |
| 1181 const float width = m_vectorWidth / scale; | |
| 1182 const float height = m_vectorHeight / scale; | |
| 1183 | |
| 1184 if (rotateAngle() == 90 || rotateAngle() == 270) { // Sideways - swop | |
| 1185 width_x_dim = (height * x_dim); | |
| 1186 height_x_dim = (width * x_dim); | |
| 1187 } else { | |
| 1188 width_x_dim = (width * x_dim); | |
| 1189 height_x_dim = (height * x_dim); | |
| 1190 } | |
| 1191 | |
| 1192 return true; | |
| 1193 } | |
| 1194 | |
| 1195 /* Return the BARCODE_XXX name of `symbology` */ | |
| 1196 QString QZint::barcodeName(const int symbology) { | |
| 1197 char buf[32]; | |
| 1198 if (ZBarcode_BarcodeName(symbology, buf) == 0) { | |
| 1199 return QString(buf); | |
| 1200 } | |
| 1201 return QSEmpty; | |
| 1202 } | |
| 1203 | |
| 1204 /* Whether Zint library "libzint" built with PNG support or not */ | |
| 1205 bool QZint::noPng() { | |
| 1206 return ZBarcode_NoPng() == 1; | |
| 1207 } | |
| 1208 | |
| 1209 /* Version of Zint library "libzint" linked to */ | |
| 1210 int QZint::getVersion() { | |
| 1211 return ZBarcode_Version(); | |
| 1212 } | |
| 1213 | |
| 1214 /* Translate settings into Command Line equivalent. Set `win` to use Windows escaping of data. | |
| 1215 If `autoHeight` set then `--height=` option will not be emitted. | |
| 1216 If HEIGHTPERROW_MODE set and non-zero `heightPerRow` given then use that for height instead of internal | |
| 1217 height */ | |
| 1218 QString QZint::getAsCLI(const bool win, const bool longOptOnly, const bool barcodeNames, const bool noEXE, | |
| 1219 const bool autoHeight, const float heightPerRow, const QString& outfile, | |
| 1220 const QZintXdimDpVars *xdimdpVars) const { | |
| 1221 QString cmd(win && !noEXE ? QSL("zint.exe") : QSL("zint")); | |
| 1222 const bool nobackground = bgColor().alpha() == 0; | |
| 1223 const bool notext = hasHRT() && !showText(); | |
| 1224 | |
| 1225 char name_buf[32]; | |
| 1226 if (barcodeNames && ZBarcode_BarcodeName(m_symbol, name_buf) == 0) { | |
| 1227 QString name(name_buf + 8); // Strip "BARCODE_" prefix | |
| 1228 arg_str(cmd, longOptOnly ? "--barcode=" : "-b ", name); | |
| 1229 } else { | |
| 1230 arg_int(cmd, longOptOnly ? "--barcode=" : "-b ", m_symbol); | |
| 1231 } | |
| 1232 | |
| 1233 if (isEANUPC()) { | |
| 1234 arg_int(cmd, "--addongap=", option2()); | |
| 1235 } | |
| 1236 | |
| 1237 if (bgStr() != QSL("FFFFFF") && !nobackground) { | |
| 1238 arg_str(cmd, "--bg=", bgStr()); | |
| 1239 } | |
| 1240 | |
| 1241 bool default_bind = false, default_bind_top = false, default_box = false, default_border = false; | |
| 1242 if (m_symbol == BARCODE_ITF14) { | |
| 1243 if ((borderType() & BARCODE_BOX) && borderWidth() == 5) { | |
| 1244 default_box = default_border = true; | |
| 1245 } | |
| 1246 } else if (m_symbol == BARCODE_CODABLOCKF || m_symbol == BARCODE_HIBC_BLOCKF || m_symbol == BARCODE_CODE16K | |
| 1247 || m_symbol == BARCODE_CODE49) { | |
| 1248 if ((borderType() & BARCODE_BIND) && borderWidth() == 1) { | |
| 1249 default_bind = default_border = true; | |
| 1250 } | |
| 1251 } else if (m_symbol == BARCODE_DPD) { | |
| 1252 if ((borderType() & BARCODE_BIND_TOP) && borderWidth() == 3) { | |
| 1253 default_bind_top = default_border = true; | |
| 1254 } | |
| 1255 } | |
| 1256 | |
| 1257 arg_bool(cmd, "--binary", (inputMode() & 0x07) == DATA_MODE); | |
| 1258 if (!default_bind) { | |
| 1259 arg_bool(cmd, "--bind", borderType() & BARCODE_BIND); | |
| 1260 } | |
| 1261 if (!default_bind_top) { | |
| 1262 arg_bool(cmd, "--bindtop", borderType() & BARCODE_BIND_TOP); | |
| 1263 } | |
| 1264 arg_bool(cmd, "--bold", !notext && (fontSetting() & BOLD_TEXT) && !isEANUPC()); | |
| 1265 if (!default_border) { | |
| 1266 arg_int(cmd, "--border=", borderWidth()); | |
| 1267 } | |
| 1268 if (!default_box) { | |
| 1269 arg_bool(cmd, "--box", borderType() & BARCODE_BOX); | |
| 1270 } | |
| 1271 arg_bool(cmd, "--cmyk", cmyk()); | |
| 1272 | |
| 1273 if (m_symbol == BARCODE_DBAR_EXPSTK || m_symbol == BARCODE_DBAR_EXPSTK_CC | |
| 1274 || m_symbol == BARCODE_PDF417 || m_symbol == BARCODE_PDF417COMP || m_symbol == BARCODE_HIBC_PDF | |
| 1275 || m_symbol == BARCODE_MICROPDF417 || m_symbol == BARCODE_HIBC_MICPDF | |
| 1276 || m_symbol == BARCODE_DOTCODE || m_symbol == BARCODE_CODABLOCKF || m_symbol == BARCODE_HIBC_BLOCKF) { | |
| 1277 arg_int(cmd, "--cols=", option2()); | |
| 1278 } | |
| 1279 | |
| 1280 arg_bool(cmd, "--compliantheight", hasCompliantHeight() && compliantHeight()); | |
| 1281 | |
| 1282 if (m_segs.empty()) { | |
| 1283 if (supportsECI()) { | |
| 1284 arg_int(cmd, "--eci=", eci()); | |
| 1285 } | |
| 1286 arg_data(cmd, longOptOnly ? "--data=" : "-d ", m_text, win); | |
| 1287 } else { | |
| 1288 arg_int(cmd, "--eci=", m_segs.front().m_eci); | |
| 1289 arg_data(cmd, longOptOnly ? "--data=" : "-d ", m_segs.front().m_text, win); | |
| 1290 for (int i = 1; i < (int) m_segs.size() && i < maxCLISegs && !m_segs[i].m_text.isEmpty(); i++) { | |
| 1291 arg_seg(cmd, i, m_segs[i], win); | |
| 1292 } | |
| 1293 } | |
| 1294 | |
| 1295 if (m_symbol == BARCODE_DATAMATRIX || m_symbol == BARCODE_HIBC_DM) { | |
| 1296 arg_bool(cmd, "--dmiso144", (option3() & DM_ISO_144) == DM_ISO_144); | |
| 1297 arg_bool(cmd, "--dmre", (option3() & 0x7F) == DM_DMRE); | |
| 1298 } | |
| 1299 | |
| 1300 if ((m_symbol == BARCODE_DOTCODE || (isDotty() && dotty())) && dotSize() != 0.8f) { | |
| 1301 arg_float(cmd, "--dotsize=", dotSize()); | |
| 1302 } | |
| 1303 if (m_symbol != BARCODE_DOTCODE && isDotty() && dotty()) { | |
| 1304 arg_bool(cmd, "--dotty", dotty()); | |
| 1305 } | |
| 1306 | |
| 1307 if (showText()) { | |
| 1308 arg_bool(cmd, "--embedfont", embedVectorFont()); | |
| 1309 } | |
| 1310 arg_bool(cmd, "--esc", inputMode() & ESCAPE_MODE); | |
| 1311 arg_bool(cmd, "--extraesc", inputMode() & EXTRA_ESCAPE_MODE); | |
| 1312 arg_bool(cmd, "--fast", inputMode() & FAST_MODE); | |
| 1313 | |
| 1314 if (fgStr() != QSL("000000") && fgStr() != QSL("000000FF")) { | |
| 1315 arg_str(cmd, "--fg=", fgStr()); | |
| 1316 } | |
| 1317 | |
| 1318 arg_bool(cmd, "--fullmultibyte", supportsFullMultibyte() && (option3() & 0xFF) == ZINT_FULL_MULTIBYTE); | |
| 1319 | |
| 1320 if (supportsGS1()) { | |
| 1321 arg_bool(cmd, "--gs1", (inputMode() & 0x07) == GS1_MODE); | |
| 1322 arg_bool(cmd, "--gs1parens", gs1Parens() || (inputMode() & GS1PARENS_MODE)); | |
| 1323 arg_bool(cmd, "--gs1nocheck", gs1NoCheck() || (inputMode() & GS1NOCHECK_MODE)); | |
| 1324 arg_bool(cmd, "--gssep", gsSep()); | |
| 1325 } | |
| 1326 | |
| 1327 if (isEANUPC() && guardDescent() != 5.0f) { | |
| 1328 arg_float(cmd, "--guarddescent=", guardDescent(), true /*allowZero*/); | |
| 1329 } | |
| 1330 if (isEANUPC() && showText()) { | |
| 1331 arg_bool(cmd, "--guardwhitespace", guardWhitespace()); | |
| 1332 } | |
| 1333 | |
| 1334 if (!autoHeight && !isFixedRatio()) { | |
| 1335 if (inputMode() & HEIGHTPERROW_MODE) { | |
| 1336 arg_float(cmd, "--height=", heightPerRow ? heightPerRow : height()); | |
| 1337 arg_bool(cmd, "--heightperrow", true); | |
| 1338 } else { | |
| 1339 arg_float(cmd, "--height=", height()); | |
| 1340 } | |
| 1341 } | |
| 1342 | |
| 1343 arg_bool(cmd, "--init", supportsReaderInit() && readerInit()); | |
| 1344 | |
| 1345 if (hasMask()) { | |
| 1346 arg_int(cmd, "--mask=", (option3() >> 8) - 1, true /*allowZero*/); | |
| 1347 } | |
| 1348 | |
| 1349 if (m_symbol == BARCODE_MAXICODE || isComposite()) { | |
| 1350 arg_int(cmd, "--mode=", option1()); | |
| 1351 } | |
| 1352 | |
| 1353 arg_bool(cmd, "--nobackground", nobackground); | |
| 1354 arg_bool(cmd, "--noquietzones", hasDefaultQuietZones() && noQuietZones()); | |
| 1355 arg_bool(cmd, "--notext", notext); | |
| 1356 arg_data(cmd, longOptOnly ? "--output=" : "-o ", outfile, win); | |
| 1357 | |
| 1358 if (m_symbol == BARCODE_MAXICODE || isComposite()) { | |
| 1359 arg_data(cmd, "--primary=", primaryMessage(), win); | |
| 1360 } | |
| 1361 | |
| 1362 arg_bool(cmd, "--quietzones", !hasDefaultQuietZones() && quietZones()); | |
| 1363 arg_int(cmd, "--rotate=", rotateAngle()); | |
| 1364 | |
| 1365 if (m_symbol == BARCODE_CODE16K || m_symbol == BARCODE_CODABLOCKF || m_symbol == BARCODE_HIBC_BLOCKF | |
| 1366 || m_symbol == BARCODE_CODE49) { | |
| 1367 arg_int(cmd, "--rows=", option1()); | |
| 1368 } else if (m_symbol == BARCODE_DBAR_EXPSTK || m_symbol == BARCODE_DBAR_EXPSTK_CC | |
| 1369 || m_symbol == BARCODE_PDF417 || m_symbol == BARCODE_PDF417COMP || m_symbol == BARCODE_HIBC_PDF) { | |
| 1370 arg_int(cmd, "--rows=", option3()); | |
| 1371 } | |
| 1372 | |
| 1373 if (dpmm()) { | |
| 1374 arg_scalexdimdp(cmd, "--scalexdimdp", scale(), dpmm(), symbol(), xdimdpVars); | |
| 1375 } else if (scale() != 1.0f) { | |
| 1376 arg_float(cmd, "--scale=", scale()); | |
| 1377 } | |
| 1378 | |
| 1379 if (m_symbol == BARCODE_MAXICODE) { | |
| 1380 arg_int(cmd, "--scmvv=", option2() - 1, true /*allowZero*/); | |
| 1381 } | |
| 1382 | |
| 1383 if (m_symbol == BARCODE_PDF417 || m_symbol == BARCODE_PDF417COMP || m_symbol == BARCODE_HIBC_PDF | |
| 1384 || m_symbol == BARCODE_AZTEC || m_symbol == BARCODE_HIBC_AZTEC | |
| 1385 || m_symbol == BARCODE_QRCODE || m_symbol == BARCODE_HIBC_QR || m_symbol == BARCODE_MICROQR | |
| 1386 || m_symbol == BARCODE_RMQR || m_symbol == BARCODE_GRIDMATRIX || m_symbol == BARCODE_HANXIN | |
| 1387 || m_symbol == BARCODE_ULTRA) { | |
| 1388 arg_int(cmd, "--secure=", option1()); | |
| 1389 } | |
| 1390 | |
| 1391 if (m_symbol == BARCODE_CODE16K || m_symbol == BARCODE_CODABLOCKF || m_symbol == BARCODE_HIBC_BLOCKF | |
| 1392 || m_symbol == BARCODE_CODE49) { | |
| 1393 arg_int(cmd, "--separator=", option3()); | |
| 1394 } | |
| 1395 | |
| 1396 arg_bool(cmd, "--small", !notext && (fontSetting() & SMALL_TEXT)); | |
| 1397 | |
| 1398 if (m_symbol == BARCODE_DATAMATRIX || m_symbol == BARCODE_HIBC_DM) { | |
| 1399 arg_bool(cmd, "--square", (option3() & 0x7F) == DM_SQUARE); | |
| 1400 } | |
| 1401 | |
| 1402 if (supportsStructApp()) { | |
| 1403 arg_structapp(cmd, "--structapp=", structAppCount(), structAppIndex(), structAppID(), win); | |
| 1404 } | |
| 1405 | |
| 1406 if (!notext && textGap() != 1.0f) { | |
| 1407 arg_float(cmd, "--textgap=", textGap(), true /*allowZero*/); | |
| 1408 } | |
| 1409 | |
| 1410 arg_bool(cmd, "--verbose", debug()); | |
| 1411 | |
| 1412 if (m_symbol == BARCODE_AZTEC || m_symbol == BARCODE_HIBC_AZTEC | |
| 1413 || m_symbol == BARCODE_MSI_PLESSEY || m_symbol == BARCODE_CODE11 | |
| 1414 || m_symbol == BARCODE_C25STANDARD || m_symbol == BARCODE_C25INTER || m_symbol == BARCODE_C25IATA | |
| 1415 || m_symbol == BARCODE_C25LOGIC || m_symbol == BARCODE_C25IND | |
| 1416 || m_symbol == BARCODE_CODE39 || m_symbol == BARCODE_HIBC_39 || m_symbol == BARCODE_EXCODE39 | |
| 1417 || m_symbol == BARCODE_LOGMARS || m_symbol == BARCODE_CODABAR | |
| 1418 || m_symbol == BARCODE_DATAMATRIX || m_symbol == BARCODE_HIBC_DM | |
| 1419 || m_symbol == BARCODE_QRCODE || m_symbol == BARCODE_HIBC_QR || m_symbol == BARCODE_MICROQR | |
| 1420 || m_symbol == BARCODE_RMQR || m_symbol == BARCODE_GRIDMATRIX || m_symbol == BARCODE_HANXIN | |
| 1421 || m_symbol == BARCODE_CHANNEL || m_symbol == BARCODE_CODEONE || m_symbol == BARCODE_CODE93 | |
| 1422 || m_symbol == BARCODE_ULTRA || m_symbol == BARCODE_VIN) { | |
| 1423 arg_int(cmd, "--vers=", option2()); | |
| 1424 } else if (m_symbol == BARCODE_DAFT && option2() != 250) { | |
| 1425 arg_int(cmd, "--vers=", option2()); | |
| 1426 } | |
| 1427 | |
| 1428 arg_int(cmd, "--vwhitesp=", vWhitespace()); | |
| 1429 arg_int(cmd, longOptOnly ? "--whitesp=" : "-w ", whitespace()); | |
| 1430 arg_bool(cmd, "--werror", warnLevel() == WARN_FAIL_ALL); | |
| 1431 | |
| 1432 return cmd; | |
| 1433 } | |
| 1434 | |
| 1435 /* `getAsCLI()` helpers */ | |
| 1436 void QZint::arg_str(QString& cmd, const char *const opt, const QString& val) { | |
| 1437 if (!val.isEmpty()) { | |
| 1438 QByteArray bstr = val.toUtf8(); | |
| 1439 cmd += QString::asprintf(" %s%.*s", opt, (int) bstr.length(), bstr.data()); | |
| 1440 } | |
| 1441 } | |
| 1442 | |
| 1443 void QZint::arg_int(QString& cmd, const char *const opt, const int val, const bool allowZero) { | |
| 1444 if (val > 0 || (val == 0 && allowZero)) { | |
| 1445 cmd += QString::asprintf(" %s%d", opt, val); | |
| 1446 } | |
| 1447 } | |
| 1448 | |
| 1449 void QZint::arg_bool(QString& cmd, const char *const opt, const bool val) { | |
| 1450 if (val) { | |
| 1451 cmd += QString::asprintf(" %s", opt); | |
| 1452 } | |
| 1453 } | |
| 1454 | |
| 1455 void QZint::arg_data(QString& cmd, const char *const opt, const QString& val, const bool win) { | |
| 1456 if (!val.isEmpty()) { | |
| 1457 QString text(val); | |
| 1458 arg_data_esc(cmd, opt, text, win); | |
| 1459 } | |
| 1460 } | |
| 1461 | |
| 1462 void QZint::arg_seg(QString& cmd, const int seg_no, const QZintSeg& val, const bool win) { | |
| 1463 QString text(val.m_text); | |
| 1464 QString opt = QString::asprintf("--seg%d=%d,", seg_no, val.m_eci); | |
| 1465 arg_data_esc(cmd, opt.toUtf8(), text, win); | |
| 1466 } | |
| 1467 | |
| 1468 void QZint::arg_data_esc(QString& cmd, const char *const opt, QString& text, const bool win) { | |
| 1469 const char delim = win ? '"' : '\''; | |
| 1470 if (win) { | |
| 1471 // Difficult (impossible?) to fully escape strings on Windows, e.g. "blah%PATH%" will substitute | |
| 1472 // env var PATH, so just doing basic escaping here | |
| 1473 text.replace("\\\\", "\\\\\\\\"); // Double-up backslashed backslash `\\` -> `\\\\` | |
| 1474 text.replace("\"", "\\\""); // Backslash quote `"` -> `\"` | |
| 1475 QByteArray bstr = text.toUtf8(); | |
| 1476 cmd += QString::asprintf(" %s%c%.*s%c", opt, delim, (int) bstr.length(), bstr.data(), delim); | |
| 1477 } else { | |
| 1478 text.replace("'", "'\\''"); // Single quote `'` -> `'\''` | |
| 1479 QByteArray bstr = text.toUtf8(); | |
| 1480 cmd += QString::asprintf(" %s%c%.*s%c", opt, delim, (int) bstr.length(), bstr.data(), delim); | |
| 1481 } | |
| 1482 } | |
| 1483 | |
| 1484 void QZint::arg_float(QString& cmd, const char *const opt, const float val, const bool allowZero) { | |
| 1485 if (val > 0 || (val == 0 && allowZero)) { | |
| 1486 cmd += QString::asprintf(" %s%g", opt, val); | |
| 1487 } | |
| 1488 } | |
| 1489 | |
| 1490 void QZint::arg_structapp(QString& cmd, const char *const opt, const int count, const int index, | |
| 1491 const QString& id, const bool win) { | |
| 1492 if (count >= 2 && index >= 1) { | |
| 1493 if (id.isEmpty()) { | |
| 1494 cmd += QString::asprintf(" %s%d,%d", opt, index, count); | |
| 1495 } else { | |
| 1496 QByteArray bstr = id.toUtf8(); | |
| 1497 arg_data(cmd, opt, QString::asprintf("%d,%d,%.*s", index, count, (int) bstr.length(), bstr.data()), | |
| 1498 win); | |
| 1499 } | |
| 1500 } | |
| 1501 } | |
| 1502 | |
| 1503 void QZint::arg_scalexdimdp(QString& cmd, const char *const opt, const float scale, const float dpmm, | |
| 1504 const int symbol, const QZintXdimDpVars *xdimdpVars) { | |
| 1505 if (dpmm) { | |
| 1506 float resolution = dpmm; | |
| 1507 float x_dim; | |
| 1508 const char *x_dim_units_str = ""; | |
| 1509 const char *resolution_units_str = ""; | |
| 1510 if (xdimdpVars && xdimdpVars->set) { | |
| 1511 x_dim = xdimdpVars->x_dim; | |
| 1512 resolution = xdimdpVars->resolution; | |
| 1513 if (xdimdpVars->x_dim_units || xdimdpVars->resolution_units) { | |
| 1514 x_dim_units_str = xdimdpVars->x_dim_units ? "in" : "mm"; | |
| 1515 resolution_units_str = xdimdpVars->resolution_units ? "dpi" : "dpmm"; | |
| 1516 } | |
| 1517 } else { | |
| 1518 x_dim = ZBarcode_XdimDp_From_Scale(symbol, scale, resolution, nullptr); | |
| 1519 } | |
| 1520 cmd += QString::asprintf(" %s=%g%s,%g%s", | |
| 1521 opt, x_dim, x_dim_units_str, resolution, resolution_units_str); | |
| 1522 } | |
| 1523 } | |
| 1524 | |
| 1525 /* Helper to return "GIF"/"SVG"(/"EMF") if `msg` false, "raster"/"vector"(/"EMF") otherwise | |
| 1526 (EMF only if `symbol` is MaxiCode) */ | |
| 1527 const char *QZintXdimDpVars::getFileType(int symbol, const struct QZintXdimDpVars *vars, bool msg) { | |
| 1528 static const char *filetypes[3] = { "GIF", "SVG", "EMF" }; | |
| 1529 static const char *msg_types[3] = { "raster", "vector", "EMF" }; | |
| 1530 | |
| 1531 if (!vars) return ""; | |
| 1532 | |
| 1533 const int idx = std::max(std::min(symbol == BARCODE_MAXICODE ? vars->filetype_maxicode | |
| 1534 : vars->filetype, 2), 0); | |
| 1535 return msg ? msg_types[idx] : filetypes[idx]; | |
| 1536 } | |
| 1537 } /* namespace Zint */ | |
| 1538 | |
| 1539 /* vim: set ts=4 sw=4 et : */ |
