Back to the Ancestors

“No one is finally dead until the ripples they cause in the world die away.”

Terry Pratchett

Christmas is a contemplative time. You meet up with friends and family and enjoy being together. Until a family member gets in touch and asks for a new printout of the family tree. Family trees were a topic on this blog in 2018 and since then it has been rather quiet on the subject.

After the Christmas holidays, the first task was therefore to search for the source code for creating the family tree. With software that hasn’t been looked at for five years, that was the first hurdle. The second hurdle was the unmaintained software. The source code was written in Java 8 and all the libraries used were outdated.

The software consists of two elements. The Java GEDCOM Reader, which reads the genealogical data from a file in GEDCOM format, and Ancestors Print, which generates a family tree in SVG format for a person from the data.

Migrating the reader to Java 21 and adapting the libraries used was not a major problem. This was mainly due to the fact that the only task of the reader, reading a line-based file format, was realized with Java on-board tools.

Unfortunately, the Ancestors Print project was a different story. In order for the geometric calculations to lead to a pleasing representation, some magic numbers and complex calculations were built in without paying particular attention to later code maintenance. When generating a new family tree, an error appeared in the graphical display, which therefore took some time to fix.

To add something interesting new to this article, the PNG format has been added to the generation of family trees. Even in the past, most family members could do little with SVG files. Unfortunately, this knowledge gap could not be closed over the years, so the family trees were manually converted into PNG files before delivery.

The article REST in Peace already showed how Batik can be used to create a PNG file from an SVG file. Since then, however, the library has only produced annual bug fix releases. A sure sign that this project is indeed dead can be seen on the demo page, which still wants to present an applet! With the release of Java 9 in 2017, support for the Java browser plug-in was officially discontinued and at that time no web browser supported this technology anymore.

Fortunately, there is a successful fork of the project under the name EchoSVG.

<dependency>
  <groupId>io.sf.carte</groupId>
  <artifactId>echosvg-transcoder</artifactId>
  <version>${echosvg.version}</version>
</dependency>

The implementation with EchoSVG is almost identical to the Batik version and therefore PNG images are now generated in the project instead of SVG images on request.

public void print(GedCom gedcom, String person, Path outputFile) throws IOException {
  String name = gedcom.findPerson(person).map(Person::getName).map(x -> x.replace("/", "")).orElseThrow();
  StringWriter stringWriter = new StringWriter();
  printer.print(gedcom, person, new PrintWriter(stringWriter));

  if (outputFile.getFileName().toString().endsWith(".png")) {
    PNGTranscoder transcoder = new PNGTranscoder();
    transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_DEFAULT_FONT_FAMILY, "Open Sans");
    String[] text = {"Copyright", "Copyright © 2025 Jens Kaiser", "Description", "Stammbaum von " + name, "Software", "EchoSVG"};

    transcoder.addTranscodingHint(PNGTranscoder.KEY_COMPRESSED_TEXT, text);
    TranscoderInput input = new TranscoderInput(outputFile.toUri().toString());
    try (StringReader reader = new StringReader(stringWriter.toString());
        FileOutputStream ostream = new FileOutputStream(outputFile.toFile())) {
      input.setReader(reader);
      transcoder.transcode(input, new TranscoderOutput(ostream));
    }
  } else if (outputFile.getFileName().toString().endsWith(".svg")) {
    Files.writeString(outputFile, stringWriter.toString());
  }
}

If the name of the output file ends with .svg, then the generated SVG content is written to the file, otherwise a PNGTranscoder is generated which receives the SVG content as input and the output is written to the output file.

This means that the whole family can finally enjoy personalized family trees again.

Leave a Comment