Flutter create Chinese character PDF file and print file in printer

4,211

Unfortunately it looks like the PDF library can only use ASCII characters. Here, I have attached code to generate a PFD with the English language. It also accesses the 'share' page of the mobile device so you can save the PDF to another app or send it to the printer via methods like AirPrint. Hope this helps. I have also re-written the code. I will make a pull request to your repo soon. You may want to file a bug report to David PHAM-VAN who is the author of the [PDF][1] library.

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_share/flutter_share.dart';
import 'package:pdf/pdf.dart';
import 'package:path_provider/path_provider.dart';

void main() => runApp(new MaterialApp(home: new MyApp()));

class MyApp extends StatelessWidget {
  Future<PDFDocument> _generateDocument() async{
    final pdf = new PDFDocument();
    final  page = new PDFPage(pdf, pageFormat: PDFPageFormat(216.0, 384.0));
    final top = page.pageFormat.height;

    final g = page.getGraphics();
    final font = new PDFFont(pdf);

    g.setColor(new PDFColor(0.3, 0.3, 0.3));
    String text = "We can only use ASCII characters";
    g.drawString(font, 12.0, text, 1.0 * PDFPageFormat.mm, top-10*PDFPageFormat.mm);

    await _localFile.then((File file){
      print("Saving local file");
      file.writeAsBytesSync(pdf.save());
    });
    return pdf;
  }

  void _sharePDF() {
    print("Print ...");
      _generateDocument().then((pdf) {
        _localPath.then((String path){
          FlutterShare.share(fileUrl: "$path/pdf.pdf");
        });
    });

  }

  Future<File> get _localFile async {
    final path = await _localPath;
    return File('$path/pdf.pdf');
  }

  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path;
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: const Text('Printing example'),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            new RaisedButton(
              child: new Text('Print Document'), onPressed: _sharePDF)
          ],
        ),
      ),
    );
  }
}

Edit: I can't figure out quickly how to send a pull request so just replace your main.dart with this code. Also this is the pubspec.yaml code you want/

name: testmanual
description: A new Flutter application.

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# Read more about versioning at semver.org.
version: 1.0.0+1

environment:
  sdk: ">=2.0.0-dev.68.0 <3.0.0"


dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  image_picker: ^0.4.10
  path_provider: "^0.4.0"
  qr_flutter: ^1.1.3
  printing: ^1.0.5
  pdf: ^1.0.6
  flutter_share: ^0.0.4
  # flutter_mailer: ^0.1.1
  # video_player: ^0.6.5
  # datetime_picker_formfield: ^0.1.3
  # device_calendar: ^0.0.6
  # connectivity: ^0.3.1
  # flutter_date_picker: ^0.1.2
  # image_form_field: ^0.0.2
  # flutter_youtube: "^1.1.1"
  # cached_network_image: ^0.4.2
  # share: ^0.5.3
  # audioplayers: ^0.7.8
  # chewie: ^0.7.0
  # font_awesome_flutter: ^8.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter


# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/ding.wav
    - assets/qpon_download.pdf
    - assets/open-sans.ttf
    - assets/GenYoMinTW-Heavy.ttf

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.io/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.io/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
#  fonts:
#     - family: Schyler
#       fonts:
#         - asset: fonts/Schyler-Regular.ttf
#         - asset: fonts/Schyler-Italic.ttf
#           style: italic
#     - family: Trajan Pro
#       fonts:
#         - asset: fonts/TrajanPro.ttf
#         - asset: fonts/TrajanPro_Bold.ttf
#           weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.io/custom-fonts/#from-packages

Edit 2:

Important! When you write the PDF to a file, this writes it directly to the phone. For example, if you are on iOS, go to the Files app and you will see a folder called <your app name> and inside, there will be 'pdf.pdf'. You may want to do a bit of cleaning or find another sharing method.

  [1]: https://pub.dartlang.org/packages/pdf
Share:
4,211
GPH
Author by

GPH

Updated on December 07, 2022

Comments

  • GPH
    GPH over 1 year

    I am trying to develop a Flutter application which can print a document to paper. I am only able to get it to work with English characters. Can someone help to make it work with Chinese please?

    Here is my main.dart

    import 'dart:convert';
    import 'dart:io';
    import 'dart:typed_data';
    import 'dart:ui';
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:pdf/pdf.dart';
    import 'package:printing/printing.dart';
    
    void main() => runApp(new MaterialApp(home: new MyApp()));
    
    class MyApp extends StatelessWidget {
      final shareWidget = new GlobalKey();
    
      Future<PDFDocument> _generateDocument() async{
        final pdf = new PDFDocument(deflate: zlib.encode);
        final page = new PDFPage(pdf, pageFormat: PDFPageFormat(216.0, 384.0));
        final g = page.getGraphics();
        final top = page.pageFormat.height;
    
    
        g.setColor(new PDFColor(0.0, 1.0, 1.0));
    
    
        var font = await rootBundle.load("assets/GenYoMinTW-Heavy.ttf");
        PDFTTFFont ttf = new PDFTTFFont(pdf, font);
    
        //PDFTTFFont ttf = new PDFTTFFont(pdf, (new File("assets/open-sans.ttf").readAsBytesSync() as Uint8List).buffer.asByteData());
        g.setColor(new PDFColor(0.3, 0.3, 0.3));
    
        //var encoded = utf8.encode("檯號: 1");
        g.drawString(ttf, 20.0, '\u4f60\u597d', 10.0 * PDFPageFormat.MM, top - 10.0 * PDFPageFormat.MM);
    
    
    
        return pdf;
      }
    
      void _printPdf() {
        print("Print ...");
    //    final pdf = _generateDocument();
    //    Printing.printPdf(document: pdf);
    
      _generateDocument().then((pdf) {
        Printing.printPdf(document: pdf);
      });
    
      }
    
    
      void _sharePdf() {
        print("Share ...");
        //final pdf = _generateDocument();
    
        // Calculate the widget center for iPad sharing popup position
        final RenderBox referenceBox =
        shareWidget.currentContext.findRenderObject();
        final topLeft =
        referenceBox.localToGlobal(referenceBox.paintBounds.topLeft);
        final bottomRight =
        referenceBox.localToGlobal(referenceBox.paintBounds.bottomRight);
        final bounds = new Rect.fromPoints(topLeft, bottomRight);
    
        _generateDocument().then((pdf) {
          Printing.sharePdf(document: pdf, bounds: bounds);
        });
    
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: const Text('Printing example'),
          ),
          body: new Center(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                new RaisedButton(
                    child: new Text('Print Document'), onPressed: _printPdf),
                new RaisedButton(
                    key: shareWidget,
                    child: new Text('Share Document'),
                    onPressed: _sharePdf),
              ],
            ),
          ),
        );
      }
    }
    

    The Screen will not go to the print preview page when using Chinese Unicode to print.

    If it helps, here is my pubspec.yaml:

    name: testmanual
    description: A new Flutter application.
    
    # The following defines the version and build number for your application.
    # A version number is three numbers separated by dots, like 1.2.43
    # followed by an optional build number separated by a +.
    # Both the version and the builder number may be overridden in flutter
    # build by specifying --build-name and --build-number, respectively.
    # Read more about versioning at semver.org.
    version: 1.0.0+1
    
    environment:
      sdk: ">=2.0.0-dev.68.0 <3.0.0"
    
    
    dependencies:
      flutter:
        sdk: flutter
    
      # The following adds the Cupertino Icons font to your application.
      # Use with the CupertinoIcons class for iOS style icons.
      cupertino_icons: ^0.1.2
      image_picker: ^0.4.10
      flutter_mailer: ^0.1.1
      video_player: ^0.6.5
      datetime_picker_formfield: ^0.1.3
      device_calendar: ^0.0.6
      connectivity: ^0.3.1
      path_provider: "^0.4.0"
      flutter_date_picker: ^0.1.2
      image_form_field: ^0.0.2
      flutter_youtube: "^1.1.1"
      cached_network_image: ^0.4.2
      qr_flutter: ^1.1.3
      share: ^0.5.3
      audioplayers: ^0.7.8
      chewie: ^0.7.0
      printing: ^1.0.5
      pdf: ^1.0.6
      font_awesome_flutter: ^8.1.0
    
    dev_dependencies:
      flutter_test:
        sdk: flutter
    
    
    # For information on the generic Dart part of this file, see the
    # following page: https://www.dartlang.org/tools/pub/pubspec
    
    # The following section is specific to Flutter.
    flutter:
    
      # The following line ensures that the Material Icons font is
      # included with your application, so that you can use the icons in
      # the material Icons class.
      uses-material-design: true
    
      # To add assets to your application, add an assets section, like this:
      assets:
        - assets/ding.wav
        - assets/qpon_download.pdf
        - assets/open-sans.ttf
        - assets/GenYoMinTW-Heavy.ttf
    
      # An image asset can refer to one or more resolution-specific "variants", see
      # https://flutter.io/assets-and-images/#resolution-aware.
    
      # For details regarding adding assets from package dependencies, see
      # https://flutter.io/assets-and-images/#from-packages
    
      # To add custom fonts to your application, add a fonts section here,
      # in this "flutter" section. Each entry in this list should have a
      # "family" key with the font family name, and a "fonts" key with a
      # list giving the asset and other descriptors for the font. For
      # example:
    #  fonts:
    #     - family: Schyler
    #       fonts:
    #         - asset: fonts/Schyler-Regular.ttf
    #         - asset: fonts/Schyler-Italic.ttf
    #           style: italic
    #     - family: Trajan Pro
    #       fonts:
    #         - asset: fonts/TrajanPro.ttf
    #         - asset: fonts/TrajanPro_Bold.ttf
    #           weight: 700
      #
      # For details regarding fonts from package dependencies,
      # see https://flutter.io/custom-fonts/#from-packages
    

    enter image description here

    • iProgram
      iProgram over 5 years
      I have not done stuff with PDFs and flutter before. Also I am on my phone at the moment so cannot check. My guess is the compiler doesn’t understand Chinese characters? If that’s the case, try inputting the Unicode characters directly. If you can’t find out how to do this soon, I’ll help when I’m on my computer.
    • GPH
      GPH over 5 years
      Thank you very much! yes, it works if i use unicode characters to print. But I have a lot of character to print, so I have to translate it to unicode and print it. I think I did it incorrectly. So it only print number instead of Chinese. I will update the code and you will see. FYI, I also put a issue in GITHUB of dart_pdf. github.com/DavBfr/dart_pdf/issues/17
    • iProgram
      iProgram over 5 years
      No problem. Happy to help! I shall add an answer on here soon so you can accept it and vote up. For now, you can use: chineseconverter.com/en/convert/unicode
    • iProgram
      iProgram over 5 years
      Also if the user inputs Chinese characters within the app, you should not have to convert it manually as the app would already do this. You only need to convert to unicode if it is hard coded into the app.
    • GPH
      GPH over 5 years
      Thank you for giving me a tool to convert Chinese character to unicode. I think I made a mistake before, it only can print unicode fo symbol , it can't print Chinese Character unicode.
    • GPH
      GPH over 5 years
      ERROR Message: [VERBOSE-2:shell.cc(181)] Dart Error: Unhandled exception: Invalid argument(s): String contains invalid characters. #0 _UnicodeSubsetEncoder.convert (dart:convert/ascii.dart:95:9) #1 Latin1Codec.encode (dart:convert/latin1.dart:44:46) #2 PDFStream.putText (file:///Users/chongto/development/flutter/.pub-cache/hosted‌​/pub.dartlang.org/pd‌​f-1.0.6/lib/src/stre‌​am.dart:79:21)
    • GPH
      GPH over 5 years
      Sorry for bring you any inconvenience!
    • iProgram
      iProgram over 5 years
      I’ll see what I can do later today. Have you seen what happens when you use the Unicode string?
    • GPH
      GPH over 5 years
      I will update the code now, then you can see it.
    • iProgram
      iProgram over 5 years
      What is on line 45 of main.dart?
    • GPH
      GPH over 5 years
      line 45 is _generateDocument().then((pdf) { Printing.printPdf(document: pdf); });
    • GPH
      GPH over 5 years
      In fact, i don't have to use pdf to print. But i only find out this method to print to printer. If there are other methods to print the Chinese character that are easy to do, please kindly adv. me. Thanks
    • iProgram
      iProgram over 5 years
    • iProgram
      iProgram over 5 years
      I have been able to get the share functionality to work with the PDF, however I don't think we can solve the issue. I think it is a issue in the PDF library.
    • GPH
      GPH over 5 years
      OK, Thank you very much for your effort! Do you know any other way to print a file to a printer? May i use txt file to print?
  • GPH
    GPH over 5 years
    May I use txt/csv file to print? will it be ok?
  • iProgram
    iProgram over 5 years
    @GPH You might be able to. Depends on how you want it to be laid out. Worth a try.
  • GPH
    GPH over 5 years
    OK, thank you so much! I only want to print Chinese characters.
  • iProgram
    iProgram over 5 years
    @GPH Unfortunately this library doesn't seem to have support for it. Unless you or someone else can find a library that supports them; or if this library is updated, this seems the only answer for now.
  • GPH
    GPH over 5 years
    Thanks again and again! I will share the answer here when I found it.
  • Max Vollmer
    Max Vollmer about 5 years
    If that is your library (as your username and the name of the author of the library suggest), you must disclose it, as otherwise this is considered spam. See How to not be a spammer