McWolke
McWolke

Reputation: 68

How to get my custom font in Apache FOP in Kotlin?

i am generating a PDF with Apache FOP.

i want to load my custom font "Interstate" in kotlin, so i can calculate the width of a text by using the font metrics.

However i can't seem to get my custom font.

I tried using the FontListGenerator but that only lists the default fonts like "Helvetica", even though the FopFactory got my configuration that contains the custom fonts.

here is my kotlin function to get a font:

private fun getFopFont(configFile: String, fontFamily: String, triplet: FontTriplet, fontSize: Int): Font? {
  // create empty FontEventListener just to satisfy FontListGenerator
  val listener: FontEventListener = object : FontEventListener {
    override fun fontLoadingErrorAtAutoDetection(source: Any, fontURL: String, e: Exception) {}
    override fun fontSubstituted(source: Any, requested: FontTriplet, effective: FontTriplet) {}
    override fun glyphNotAvailable(source: Any, ch: Char, fontName: String) {}
    override fun fontDirectoryNotFound(source: Any, msg: String) {}
    override fun svgTextStrokedAsShapes(source: Any, fontFamily: String) {}
  }

  val listGenerator = FontListGenerator()
  val fopFactory = FopFactory.newInstance(File(configFile).toURI())

  @Suppress("UNCHECKED_CAST")
  val fontFamilies = listGenerator.listFonts(fopFactory, MimeConstants.MIME_PDF, listener) as SortedMap<String, List<FontSpec>>
  val fontSpec = fontFamilies[fontFamily] as ArrayList<FontSpec>? ?: return null

  return fontSpec.filter {spec -> spec.triplets.contains(triplet)}
    .map {Font(fontFamily, triplet, it.fontMetrics, fontSize)}
    .firstOrNull()
}

Upvotes: 1

Views: 136

Answers (1)

McWolke
McWolke

Reputation: 68

i found my mistake. the fopFactory i used in my code wasn't properly loading my fonts it seems. to fix that i used the FopConfParser to parse my config file and used the fopFactoryBuilder of the parser to get the fopFactory.

fop factory creation:

private fun createFopFactory(fopConfiguration: URL): FopFactory {
    try {
        fopConfiguration.openStream().use {fopConfigurationStream ->
            // FontResourceResolver is my custom resource resolver to load font resources
            val parser = FopConfParser(fopConfigurationStream, fopConfiguration.toURI(), FontResourceResolver()) 
            val builder = parser.fopFactoryBuilder
            return builder.build()
        }
    } catch (e: Exception) {
        throw PDFServiceException("Could not initialize FOP factory", e)
    }
}

Upvotes: 1

Related Questions