Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add Arabic chars in flutter pdf generating #1808

Open
alialdwahy opened this issue Jan 16, 2025 · 0 comments
Open

How to add Arabic chars in flutter pdf generating #1808

alialdwahy opened this issue Jan 16, 2025 · 0 comments
Labels
bug Something isn't working needs triage

Comments

@alialdwahy
Copy link

Image

Future generateQrCodeImage(String qrData) async {
final qrCode = QrPainter(
data: qrData,
version: QrVersions.auto,
gapless: true,
);
final picData = await qrCode.toImageData(120);
return picData!.buffer.asUint8List();
}

pw.Widget buildTextEn(String text, PdfColor color, double fontSize,
{pw.Font? font, pw.FontWeight fontWeight = pw.FontWeight.normal}) {
return pw.Text(
text,
style: pw.TextStyle(
color: color,
fontSize: fontSize,
fontWeight: fontWeight,
font: font,
),
);
}

pw.Widget buildTextAr(String text, PdfColor color, double fontSize,
{pw.Font? font,
required List<pw.Font> fontFallback,
pw.FontWeight fontWeight = pw.FontWeight.normal}) {
return pw.Text(
text,
textDirection: pw.TextDirection.rtl,
style: pw.TextStyle(
color: color,
fontSize: fontSize,
fontWeight: fontWeight,
fontFallback: fontFallback,
font: font,
),
);
}

pw.Widget buildSectionHeader(String englishText, String arabicText,
PdfColor backgroundColor, pw.Font arabicFont) {
return pw.Container(
decoration: pw.BoxDecoration(
color: backgroundColor,
borderRadius: pw.BorderRadius.circular(5.0),
),
child: pw.Padding(
padding: pw.EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0),
child: pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: [
buildTextEn(englishText, PdfColors.white, 14.0,
fontWeight: pw.FontWeight.bold),
buildTextAr(arabicText, PdfColors.white, 14.0,
fontFallback: [arabicFont], fontWeight: pw.FontWeight.bold),
],
),
),
);
}

Future taxInvoicePdf(
String qrData,
double vatAmount,
double appAmount,
InvoiceRecord invoiceDoc,
CustomerCompaniesRecord customerCompanyDoc,
) async {
final qrImageData = await generateQrCodeImage(qrData);

final pdf = pw.Document();
final textGray = PdfColor.fromHex('#57636C');
final dividerColor = PdfColor.fromHex('#EAECF0');
final greenContainer = PdfColor.fromHex('#7C9587');
final arabi = await PdfGoogleFonts.tajawalBold();

pdf.addPage(
pw.Page(
build: (pw.Context context) {
return pw.Column(
mainAxisSize: pw.MainAxisSize.max,
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
buildTextEn('Invoice ID: ${invoiceDoc.invoiceId}', textGray, 14.0),
pw.Padding(
padding: pw.EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 5.0),
child: buildTextEn(
'Date: ${DateFormat('yyyy-MM-dd').format(invoiceDoc.invoiceCreationDate!)}',
textGray,
14.0),
),

        pw.Divider(
          height: 1.0,
          thickness: 2.0,
          color: dividerColor,
        ),

        pw.Padding(
          padding: pw.EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0),
          child: buildSectionHeader('Seller information', 'معلومات البائع',
              greenContainer, arabi),
        ),
        buildSellerDetailsSection(arabi),

        pw.SizedBox(height: 10),

        buildSectionHeader(
            'Buyer information', 'معلومات المشتري', greenContainer, arabi),
        buildBuyerDetailsSection(arabi, customerCompanyDoc),
        pw.SizedBox(height: 10),

        buildSectionHeader(
            'Product details', 'تفاصيل المنتج', greenContainer, arabi),
        pw.SizedBox(height: 5),

        buildProductTableDetailsSection(arabi, appAmount),

        buildProductDetailsSection(arabi, invoiceDoc, vatAmount, appAmount),
        pw.SizedBox(height: 15),

        // previous code

        pw.Row(
          mainAxisAlignment: pw.MainAxisAlignment.center,
          children: [
            pw.Container(
              width: 120,
              height: 120,
              child: pw.Image(
                pw.MemoryImage(qrImageData),
              ),
            ),
          ],
        ),
      ],
    );
  },
),

);

final bytes = await pdf.save();
return FFUploadedFile(
name: "taxInvoice_${invoiceDoc.invoiceId}", bytes: bytes);
}

pw.Widget buildSellerDetailsSection(pw.Font arabicFont) {
final textGray = PdfColor.fromHex('#57636C');
final dividerColor = PdfColor.fromHex('#EAECF0');

return pw.Padding(
padding: pw.EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 0.0),
child: pw.Column(
mainAxisSize: pw.MainAxisSize.max,
children: [
buildDetailsRow('Company Name :', ': اسم الشركة', arabicFont),
buildTextEn(
"Al-Rabt al-'Alami For Advertising Services", textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow('Address :', ': العنوان', arabicFont),
buildTextEn('King Abdullah Bin Abdulaziz Rd', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow('VAT Number :', ': الرقم الضريبي', arabicFont),
buildTextEn('311274337100003', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow('Commercial Number :', ': رقم السجل التجاري', arabicFont),
buildTextEn('1010797959', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
],
),
);
}

pw.Widget buildBuyerDetailsSection(
pw.Font arabicFont, CustomerCompaniesRecord customerCompany) {
final textGray = PdfColor.fromHex('#57636C');
final dividerColor = PdfColor.fromHex('#EAECF0');

return pw.Padding(
padding: pw.EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 0.0),
child: pw.Column(
mainAxisSize: pw.MainAxisSize.max,
children: [
buildDetailsRow('Name :', ': اسم', arabicFont),
buildTextEn('${customerCompany.companyName}', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow('Address :', ': عنوان', arabicFont),
buildTextEn('${customerCompany.countryName}', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow('VAT Number :', ': الرقم الضريبي', arabicFont),
buildTextEn('${customerCompany.vATNumber}', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow('Commercial Number :', ': رقم السجل التجاري', arabicFont),
buildTextEn('${customerCompany.commercialNumber}', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
],
),
);
}

pw.Widget buildProductTableDetailsSection(pw.Font arabicFont, double price) {
final headerColor = PdfColor.fromHex('#F3F3F3');
final textGray = PdfColor.fromHex('#57636C');
final dividerColor = PdfColor.fromHex('#DBDBDB');

return pw.ClipRRect(
horizontalRadius: 5.0,
verticalRadius: 5.0,
child: pw.Table(
border:
pw.TableBorder.symmetric(inside: pw.BorderSide(color: dividerColor)),
children: [
pw.TableRow(
decoration: pw.BoxDecoration(
color: headerColor,
),
children: [
pw.Container(
padding: pw.EdgeInsets.all(5.0),
alignment: pw.Alignment.center,
child: pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.start,
children: [
buildTextEn("Product ", PdfColors.black, 10.0,
fontWeight: pw.FontWeight.bold),
buildTextAr("منتج", PdfColors.black, 10.0,
fontFallback: [arabicFont],
fontWeight: pw.FontWeight.bold),
],
),
),
pw.Container(
padding: pw.EdgeInsets.all(5.0),
alignment: pw.Alignment.center,
child: pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.start,
children: [
buildTextEn("Price ", PdfColors.black, 10.0,
fontWeight: pw.FontWeight.bold),
buildTextAr("سعر", PdfColors.black, 10.0,
fontFallback: [arabicFont],
fontWeight: pw.FontWeight.bold),
],
),
),
pw.Container(
padding: pw.EdgeInsets.all(5.0),
alignment: pw.Alignment.center,
child: pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.start,
children: [
buildTextEn("Quantity ", PdfColors.black, 10.0,
fontWeight: pw.FontWeight.bold),
buildTextAr("كمية", PdfColors.black, 10.0,
fontFallback: [arabicFont],
fontWeight: pw.FontWeight.bold),
],
),
),
],
),
pw.TableRow(
decoration: pw.BoxDecoration(
color: headerColor,
),
children: [
pw.Padding(
padding: pw.EdgeInsets.all(5.0),
child: buildTextEn("Advertisement commission", textGray, 10.0),
),
pw.Padding(
padding: pw.EdgeInsets.all(5.0),
child: buildTextEn('$price', textGray, 10.0),
),
pw.Padding(
padding: pw.EdgeInsets.all(5.0),
child: buildTextEn("1", textGray, 10.0),
),
],
),
],
),
);
}

pw.Widget buildProductDetailsSection(
pw.Font arabicFont, InvoiceRecord invoice, double vat, double gt) {
final textGray = PdfColor.fromHex('#57636C');
final dividerColor = PdfColor.fromHex('#EAECF0');

return pw.Padding(
padding: pw.EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 0.0),
child: pw.Column(
mainAxisSize: pw.MainAxisSize.max,
children: [
buildDetailsRow(
'VAT percentage :', ': نسبة ضريبة القيمة المضافة', arabicFont),
buildTextEn('${invoice.invoiceVat2}%', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow(
'VAT value :', ': قيمة ضريبة القيمة المضافة', arabicFont),
buildTextEn('$vat', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow('Total without VAT :',
': الإجمالي بدون ضريبة القيمة المضافة', arabicFont),
buildTextEn('$gt', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
buildDetailsRow(
'Total with VAT :', ': الإجمالي مع ضريبة القيمة المضافة', arabicFont),
buildTextEn('${gt + vat}', textGray, 10.0),
pw.Divider(height: 1.0, thickness: 2.0, color: dividerColor),
],
),
);
}

pw.Widget buildDetailsRow(
String englishText, String arabicText, pw.Font arabicFont) {
englishText = englishText.replaceAll(":", '');
arabicText = arabicText.replaceAll(":", '');
return pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: [
buildTextEn(englishText, PdfColors.black, 10.0,
fontWeight: pw.FontWeight.bold),
buildTextAr(arabicText, PdfColors.black, 10.0,
fontFallback: [arabicFont], fontWeight: pw.FontWeight.bold),
],
);
}

@alialdwahy alialdwahy added bug Something isn't working needs triage labels Jan 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs triage
Projects
None yet
Development

No branches or pull requests

1 participant