tdf#139778 Switch to ZXing for generating QR code
Change-Id: Ief944266d5183bb862afe99ec6b0bdaca4956938 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112534 Tested-by: Jenkins Tested-by: René Engelhard <rene@debian.org> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
committed by
Mike Kaganski
parent
f72cd65eef
commit
cdeb5046be
+1
-1
@@ -73,7 +73,7 @@ $(eval $(call gb_Library_use_externals,cui,\
|
||||
libxml2 \
|
||||
orcus-parser \
|
||||
orcus \
|
||||
qrcodegen \
|
||||
zxing \
|
||||
))
|
||||
ifeq ($(DISABLE_GUI),)
|
||||
$(eval $(call gb_Library_use_externals,cui,\
|
||||
|
||||
@@ -17,14 +17,26 @@
|
||||
#include <utility>
|
||||
#include <vcl/svapp.hxx>
|
||||
|
||||
#if ENABLE_QRCODEGEN
|
||||
#if defined(SYSTEM_QRCODEGEN)
|
||||
#include <qrcodegen/QrCode.hpp>
|
||||
#else
|
||||
#include <QrCode.hpp>
|
||||
#if ENABLE_ZXING
|
||||
#include <rtl/ustrbuf.hxx>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
|
||||
#include <BarcodeFormat.h>
|
||||
#include <BitArray.h>
|
||||
#include <BitMatrix.h>
|
||||
#include <MultiFormatWriter.h>
|
||||
#include <TextUtfEncoding.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // ENABLE_ZXING
|
||||
|
||||
#include <com/sun/star/beans/XPropertySet.hpp>
|
||||
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
|
||||
#include <com/sun/star/drawing/XShape.hpp>
|
||||
@@ -56,9 +68,37 @@ using namespace css::sheet;
|
||||
using namespace css::text;
|
||||
using namespace css::drawing;
|
||||
using namespace css::graphic;
|
||||
#if ENABLE_QRCODEGEN
|
||||
using namespace qrcodegen;
|
||||
namespace
|
||||
{
|
||||
#if ENABLE_ZXING
|
||||
// Implementation adapted from the answer: https://stackoverflow.com/questions/10789059/create-qr-code-in-vector-image/60638350#60638350
|
||||
OUString ConvertToSVGFormat(const ZXing::BitMatrix& bitmatrix)
|
||||
{
|
||||
OUStringBuffer sb;
|
||||
const int width = bitmatrix.width();
|
||||
const int height = bitmatrix.height();
|
||||
ZXing::BitArray row(width);
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 "
|
||||
+ OUString::number(width) + " " + OUString::number(height)
|
||||
+ "\" stroke=\"none\">\n"
|
||||
"<path d=\"");
|
||||
for (int i = 0; i < height; ++i)
|
||||
{
|
||||
bitmatrix.getRow(i, row);
|
||||
for (int j = 0; j < width; ++j)
|
||||
{
|
||||
if (row.get(j))
|
||||
{
|
||||
sb.append("M" + OUString::number(j) + "," + OUString::number(i) + "h1v1h-1z");
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append("\"/>\n</svg>");
|
||||
return sb.toString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QrCodeGenDialog::QrCodeGenDialog(weld::Widget* pParent, Reference<XModel> xModel,
|
||||
bool bEditExisting)
|
||||
@@ -70,7 +110,7 @@ QrCodeGenDialog::QrCodeGenDialog(weld::Widget* pParent, Reference<XModel> xModel
|
||||
m_xBuilder->weld_radio_button("button_quartile"),
|
||||
m_xBuilder->weld_radio_button("button_high") }
|
||||
, m_xSpinBorder(m_xBuilder->weld_spin_button("edit_border"))
|
||||
#if ENABLE_QRCODEGEN
|
||||
#if ENABLE_ZXING
|
||||
, mpParent(pParent)
|
||||
#endif
|
||||
{
|
||||
@@ -108,7 +148,7 @@ QrCodeGenDialog::QrCodeGenDialog(weld::Widget* pParent, Reference<XModel> xModel
|
||||
|
||||
short QrCodeGenDialog::run()
|
||||
{
|
||||
#if ENABLE_QRCODEGEN
|
||||
#if ENABLE_ZXING
|
||||
short nRet;
|
||||
while (true)
|
||||
{
|
||||
@@ -120,7 +160,7 @@ short QrCodeGenDialog::run()
|
||||
Apply();
|
||||
break;
|
||||
}
|
||||
catch (const qrcodegen::data_too_long&)
|
||||
catch (const std::exception&)
|
||||
{
|
||||
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
|
||||
mpParent, VclMessageType::Warning, VclButtonsType::Ok,
|
||||
@@ -139,7 +179,7 @@ short QrCodeGenDialog::run()
|
||||
|
||||
void QrCodeGenDialog::Apply()
|
||||
{
|
||||
#if ENABLE_QRCODEGEN
|
||||
#if ENABLE_ZXING
|
||||
css::drawing::QRCode aQRCode;
|
||||
aQRCode.Payload = m_xEdittext->get_text();
|
||||
|
||||
@@ -264,43 +304,41 @@ void QrCodeGenDialog::Apply()
|
||||
|
||||
OUString QrCodeGenDialog::GenerateQRCode(OUString aQRText, tools::Long aQRECC, int aQRBorder)
|
||||
{
|
||||
#if ENABLE_QRCODEGEN
|
||||
//Select ECC:: value from aQrECC
|
||||
qrcodegen::QrCode::Ecc bqrEcc = qrcodegen::QrCode::Ecc::LOW;
|
||||
#if ENABLE_ZXING
|
||||
// Associated ZXing error correction levels (0-8) to our constants arbitrarily.
|
||||
int bqrEcc = 1;
|
||||
|
||||
switch (aQRECC)
|
||||
{
|
||||
case 1:
|
||||
case css::drawing::QRCodeErrorCorrection::LOW:
|
||||
{
|
||||
bqrEcc = qrcodegen::QrCode::Ecc::LOW;
|
||||
bqrEcc = 1;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case css::drawing::QRCodeErrorCorrection::MEDIUM:
|
||||
{
|
||||
bqrEcc = qrcodegen::QrCode::Ecc::MEDIUM;
|
||||
bqrEcc = 3;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
case css::drawing::QRCodeErrorCorrection::QUARTILE:
|
||||
{
|
||||
bqrEcc = qrcodegen::QrCode::Ecc::QUARTILE;
|
||||
bqrEcc = 5;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case css::drawing::QRCodeErrorCorrection::HIGH:
|
||||
{
|
||||
bqrEcc = qrcodegen::QrCode::Ecc::HIGH;
|
||||
bqrEcc = 7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//OuString to char* qrtext
|
||||
OString o = OUStringToOString(aQRText, RTL_TEXTENCODING_UTF8);
|
||||
const char* qrtext = o.pData->buffer;
|
||||
|
||||
// From QR Code library
|
||||
qrcodegen::QrCode qr0 = qrcodegen::QrCode::encodeText(qrtext, bqrEcc);
|
||||
std::string svg = qr0.toSvgString(aQRBorder);
|
||||
//cstring to OUString
|
||||
return OUString::createFromAscii(svg.c_str());
|
||||
std::string QRText(o.getStr(), o.getLength());
|
||||
ZXing::BarcodeFormat format = ZXing::BarcodeFormatFromString("QR_CODE");
|
||||
auto writer = ZXing::MultiFormatWriter(format).setMargin(aQRBorder).setEccLevel(bqrEcc);
|
||||
writer.setEncoding(ZXing::CharacterSet::UTF8);
|
||||
ZXing::BitMatrix bitmatrix = writer.encode(ZXing::TextUtfEncoding::FromUtf8(QRText), 0, 0);
|
||||
return ConvertToSVGFormat(bitmatrix);
|
||||
#else
|
||||
(void)aQRText;
|
||||
(void)aQRECC;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <config_qrcodegen.h>
|
||||
#include <config_zxing.h>
|
||||
|
||||
#include <vcl/weld.hxx>
|
||||
|
||||
@@ -33,7 +33,7 @@ private:
|
||||
std::unique_ptr<weld::Entry> m_xEdittext;
|
||||
std::unique_ptr<weld::RadioButton> m_xECC[4];
|
||||
std::unique_ptr<weld::SpinButton> m_xSpinBorder;
|
||||
#if ENABLE_QRCODEGEN
|
||||
#if ENABLE_ZXING
|
||||
weld::Widget* mpParent;
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user