Search code examples
androidkotlinpdffonts

can't load a font from my res/font inside fragment to use in pdfDocument


I want to generate a pdf document inside my fragment ... I want to change font because that default font ammit persian/arabic chars ... I use below code to load a font :

val fontData = context.assets.open("font/yekanbakh.ttf").readBytes() val fontProgram = FontProgramFactory.createFont(fontData) val myFont = PdfFontFactory.createFont(fontProgram, PdfEncodings.IDENTITY_H, true)

                val document = Document(pdfDocument, PageSize.A4)


                document.add(Paragraph(line1).setFont(myFont))
                document.add(Paragraph(line2).setFont(myFont))

but I got below error :

ava.io.FileNotFoundException: font/yekanbakh.ttf

I stil try to context.assets.open("fonts/yekanbakh.ttf").readBytes().

but I failed and got same error ... the full code is :

val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)

        val name = "hoghugh${Random.nextInt(1..1000)}"
        val myFile = File(dir, "$name.pdf")

        try {
            val fileOutputStream = FileOutputStream(myFile)
            val pdfWriter = PdfWriter(fileOutputStream)
            val pdfDocument = PdfDocument(pdfWriter)

            val typeface = ResourcesCompat.getFont(requireContext(),R.font.yekanbakh)
            val context = requireContext()

            try {
                val fontData = context.assets.open("font/yekanbakh.ttf").readBytes()
                val fontProgram = FontProgramFactory.createFont(fontData)
                val myFont = PdfFontFactory.createFont(fontProgram, PdfEncodings.IDENTITY_H, true)

                val document = Document(pdfDocument, PageSize.A4)


                document.add(Paragraph(line1).setFont(myFont))
                document.add(Paragraph(line2).setFont(myFont))


                val table1 = Table(subHeaders1.size)
                    .useAllAvailableWidth()
                    .setFontSize(10f)

                subHeaders1.forEach { col ->
                    table1.addHeaderCell(col)
                }
                body1.forEach { row ->
                    row.forEach { col ->
                        table1.addCell(col.toString())
                    }
                }
                document.add(table1)


                val table2 = Table(subHeaders2.size)
                    .useAllAvailableWidth()
                    .setFontSize(10f)

                subHeaders2.forEach { col ->
                    table2.addHeaderCell(col.toString())
                }
                body2.forEach { row ->
                    row.forEach { col ->
                        table2.addCell(col.toString())
                    }
                }
                document.add(table2)


                val table3 = Table(subHeaders3.size)
                    .useAllAvailableWidth()
                    .setFontSize(10f)

                subHeaders3.forEach { col ->
                    table3.addHeaderCell(col)
                }
                body1.forEach { row ->
                    row.forEach { col ->
                        table3.addCell(col.toString())
                    }
                }
                document.add(table3)

                document.add(Paragraph(line3))

                document.close()
                fileOutputStream.close()

Solution

  • Your code is correct, you have fonts in wrong directory, you have to put it in assets directory. AssetsManager from context is working with assets directory, not the res.

    With Android studio create assets folder like this: File -> New -> Folder -> Assets Folder, and put your font in it. It should look like in the picture:

    enter image description here

    Directory font is used for defining fonts your app will use for showing text, you can't load font as byte array from there.