TomRoush / PdfBox-Android

The Apache PdfBox project ported to work on Android
Apache License 2.0
987 stars 257 forks source link

Cannot load glyphs #408

Closed muhammadn closed 2 years ago

muhammadn commented 2 years ago

Describe the bug cannot load glyphs

To reproduce Code snippet to reproduce the behavior:

import com.hp.jipp.model.MediaSource
import com.hp.jipp.model.Sides
import com.hp.jipp.pdl.ColorSpace
import com.hp.jipp.pdl.OutputSettings
import com.hp.jipp.pdl.RenderableDocument
import com.hp.jipp.pdl.RenderablePage
import com.hp.jipp.pdl.pclm.PclmSettings
import com.hp.jipp.pdl.pclm.PclmWriter
import com.hp.jipp.pdl.pwg.PwgSettings
import com.hp.jipp.pdl.pwg.PwgWriter

import com.tom_roush.pdfbox.pdmodel.PDDocument
import com.tom_roush.pdfbox.pdmodel.PDPageTree
import com.tom_roush.pdfbox.rendering.ImageType
import com.tom_roush.pdfbox.rendering.PDFRenderer

class MainActivity: FlutterActivity() {
  private val DPI = 300
  private val IMAGE_TYPE: ImageType = ImageType.RGB
  private val RED_COEFFICIENT = 0.2126
  private val GREEN_COEFFICIENT = 0.7512
  private val BLUE_COEFFICIENT = 0.0722

    fun printIpp(ippUrl: String?, mode: String?, document: String?, numCopies: Int?, pages: String?) {
      val policy: StrictMode.ThreadPolicy = StrictMode.ThreadPolicy.Builder().permitAll().build()
      StrictMode.setThreadPolicy(policy)

      // initialize printer connection and show printer attributes
      val ippPrinter = IppPrinter(URI.create(ippUrl))
      ippPrinter.attributes.logDetails()

      // document URl (printer will download document)
      //val remoteFile = URI.create(documentUrl)
      //ippPrinter.printUri(remoteFile)

      Log.d("DEBUG", "number of copies: " + numCopies)

      // write to a temporary folder
      //val file = File.createTempFile("document", null, context.getCacheDir())
      val file = File(context.filesDir, "document.pdf")
      file.writeBytes(Base64.decode(document, Base64.DEFAULT))

      // conversion from PDF to PCLm

      val outputFormat = OutputFormat.toOutputFormat("pwg_raster")

//      val pdfInputStream: InputStream = BufferedInputStream(FileInputStream(file))
//      val outputStream: OutputStream = BufferedOutputStream(FileOutputStream(file))

      val size = file.length()
      println("1: The file size is $size bytes")

      val colorSpace: ColorSpace = convertImageTypeToColorSpace(IMAGE_TYPE)
      PDDocument.load(BufferedInputStream(FileInputStream(file))).use { document ->
        println("2: The file size is $size bytes")

        val pdfRenderer = PDFRenderer(document)
        val pages: PDPageTree = document.getPages()
        val renderablePages: MutableList<RenderablePage> = ArrayList<RenderablePage>()
        for (pageIndex in 0 until pages.getCount()) {
          val image: Bitmap = pdfRenderer.renderImageWithDPI(pageIndex, DPI.toFloat(), IMAGE_TYPE)
          val width: Int = image.getWidth()
          val height: Int = image.getHeight()
          val renderablePage: RenderablePage = object : RenderablePage(width, height) {
            override fun render(yOffset: Int, swathHeight: Int, colorSpace: ColorSpace, byteArray: ByteArray) {
              var red: Int
              var green: Int
              var blue: Int
              var rgb: Int
              var byteIndex = 0
              for (y in yOffset until yOffset + swathHeight) {
                for (x in 0 until width) {
                  rgb = image.getPixel(x, y)
                  red = rgb shr 16 and 0xFF
                  green = rgb shr 8 and 0xFF
                  blue = rgb and 0xFF
                  if (colorSpace === ColorSpace.Grayscale) {
                    byteArray[byteIndex++] = (RED_COEFFICIENT * red + GREEN_COEFFICIENT * green + BLUE_COEFFICIENT * blue).toInt().toByte()
                  } else {
                    byteArray[byteIndex++] = red.toByte()
                    byteArray[byteIndex++] = green.toByte()
                    byteArray[byteIndex++] = blue.toByte()
                  }
                }
              }
            }
          }
          renderablePages.add(renderablePage)
        }
        val renderableDocument = object: RenderableDocument() {
          override fun iterator() = renderablePages.iterator()
          override val dpi: Int = DPI
        }
        when (outputFormat) {
          OutputFormat.PCLM -> saveRenderableDocumentAsPCLm(renderableDocument, colorSpace, FileOutputStream(file))
         }
      }
 }

PDF example (20 APRIL 2021M) KENYATAAN AKHBAR KEBENARAN SOLAT JUMAAT, SOLAT FARDU DAN SOLAT SUNAT TERAWIH SERTA AKTIVITI-AKTIVITI PENGIMARAHAN MASJID KELANTAN 2021. - Copy (3) (1) (1).pdf

Expected behavior No error when initialising pdfbox Actual behavior NullException error when initialising pdfbox

Environment details:

Additional context Stacktrace:

D/PdfBox-Android(20528): No PostScript name information is provided for the font Calibri
D/PdfBox-Android(20528): Type 7 GSUB lookup table is not supported and will be ignored
E/AndroidRuntime(20528): FATAL EXCEPTION: main
E/AndroidRuntime(20528): Process: com.example.print_kiosk, PID: 20528
E/AndroidRuntime(20528): java.lang.ExceptionInInitializerError
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.encoding.GlyphList.getAdobeGlyphList(GlyphList.java:93)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.PDSimpleFont.assignGlyphList(PDSimpleFont.java:425)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.PDSimpleFont.readEncoding(PDSimpleFont.java:124)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.PDTrueTypeFont.<init>(PDTrueTypeFont.java:222)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.PDFontFactory.createFont(PDFontFactory.java:87)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.PDResources.getFont(PDResources.java:145)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.contentstream.operator.text.SetFontAndSize.process(SetFontAndSize.java:62)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.contentstream.PDFStreamEngine.processOperator(PDFStreamEngine.java:933)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:515)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:489)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.contentstream.PDFStreamEngine.processPage(PDFStreamEngine.java:154)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.rendering.PageDrawer.drawPage(PageDrawer.java:252)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.rendering.PDFRenderer.renderImage(PDFRenderer.java:282)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.rendering.PDFRenderer.renderImage(PDFRenderer.java:203)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.rendering.PDFRenderer.renderImageWithDPI(PDFRenderer.java:189)
E/AndroidRuntime(20528):    at com.example.print_kiosk.MainActivity.printIpp(MainActivity.kt:130)
E/AndroidRuntime(20528):    at com.example.print_kiosk.MainActivity.configureFlutterEngine$lambda-0(MainActivity.kt:81)
E/AndroidRuntime(20528):    at com.example.print_kiosk.MainActivity.lambda$MVRHuMVxTk_XzJjb9K1GttzzMOU(Unknown Source:0)
E/AndroidRuntime(20528):    at com.example.print_kiosk.-$$Lambda$MainActivity$MVRHuMVxTk_XzJjb9K1GttzzMOU.onMethodCall(Unknown Source:2)
E/AndroidRuntime(20528):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262)
E/AndroidRuntime(20528):    at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:178)
E/AndroidRuntime(20528):    at io.flutter.embedding.engine.dart.DartMessenger.lambda$handleMessageFromDart$0$DartMessenger(DartMessenger.java:206)
E/AndroidRuntime(20528):    at io.flutter.embedding.engine.dart.-$$Lambda$DartMessenger$6ZD1MYkhaLxyPjtoFDxe45u43DI.run(Unknown Source:12)
E/AndroidRuntime(20528):    at android.os.Handler.handleCallback(Handler.java:883)
E/AndroidRuntime(20528):    at android.os.Handler.dispatchMessage(Handler.java:100)
E/AndroidRuntime(20528):    at android.os.Looper.loop(Looper.java:214)
E/AndroidRuntime(20528):    at android.app.ActivityThread.main(ActivityThread.java:7356)
E/AndroidRuntime(20528):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(20528):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/AndroidRuntime(20528):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
E/AndroidRuntime(20528): Caused by: java.lang.NullPointerException
E/AndroidRuntime(20528):    at java.io.Reader.<init>(Reader.java:78)
E/AndroidRuntime(20528):    at java.io.InputStreamReader.<init>(InputStreamReader.java:97)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.encoding.GlyphList.loadList(GlyphList.java:141)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.encoding.GlyphList.<init>(GlyphList.java:122)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.encoding.GlyphList.load(GlyphList.java:62)
E/AndroidRuntime(20528):    at com.tom_roush.pdfbox.pdmodel.font.encoding.GlyphList.<clinit>(GlyphList.java:38)
E/AndroidRuntime(20528):    ... 30 more
TomRoush commented 2 years ago

It sounds like you did not call PDFBoxResourceLoader.init(getApplicationContext()). You need to add this somewhere before you use any PdfBox-Android functions

muhammadn commented 2 years ago

@TomRoush Thank you! I missed that part. added it and it works.

here is an example for others who are using flutter to call this library:

 override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
      call, result ->

      if (call.method == "printIpp") {
        val ippUrl = call.argument<String?>("ippUrl")
        val mode = call.argument<String?>("mode")
        val document = call.argument<String?>("document")
        val numCopies = call.argument<Int?>("copies")
        val pages = call.argument<String?>("pages")

        // here is the solution
        PDFBoxResourceLoader.init(getApplicationContext())

        // send document to printer to print
        printIpp(ippUrl, mode, document, numCopies, pages)

        // successful operation, return to app
        result.success(null)
      } else {
        result.notImplemented()
      }
    }
  }