Hi,

I think the problem is with PDF graphics 2d, not with PDFBox.

I can tell you if the fonts are really not embedded if you upload the PDF to a sharehoster.

Tilman

Am 14.03.2021 um 19:27 schrieb Thangalin:
  Hi list!

Attempting to render an SVG file read from Batik onto an exported PDF
document has encountered a few problems, including:

    - Font rasterization
    - Font weights
    - Grid marks
    - Colour

*Versions*

    - Apache PDFBox 2.0.22
    - Apache Batik 1.14
    - Rototor's PDF Graphics 2D 0.31
    - OpenJDK 15
    - Linux kernel 5.9.14, XFCE on Arch

*Fonts*

    - Roboto, Roboto Thin -
    https://fonts.google.com/specimen/Roboto?preview.text_type=custom
    - Daggersquare - https://www.dafont.com/daggersquare.font

*Comparison*

In the following image, PDFBox export is on the left and Inkscape export on
the right, but sourced from the same SVG and font files:

https://i.ibb.co/pdxrf06/pdfbox-inkscape.png

Notice that:

    - the word WANTED is discoloured (not a big issue);
    - fine lines grid the entire image (especially visible against the
    WANTED text);
    - all text is rasterized;
    - the font weight (Roboto thin) is not honoured; and
    - the file sizes differ by a fair margin (also not a huge issue).

inkscape-poster.pdf is 23,481 bytes
pdfbox-poster.pdf is 493,896 bytes

*Question*

How do you force the font subsets to be embedded (to reduce PDF file size
and avoid rasterizing glyphs)?

*SSCCE*

The SSCCE transcodes /tmp/poster.svg to /tmp/pdfbox-poaster.pdf:

// SOF
import de.rototor.pdfbox.graphics2d.PdfBoxGraphics2D;
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;

import java.io.File;
import java.util.Map;

import static java.awt.RenderingHints.*;
import static java.awt.geom.AffineTransform.getScaleInstance;
import static java.nio.file.Files.newOutputStream;
import static java.nio.file.StandardOpenOption.*;
import static
org.apache.batik.util.XMLResourceDescriptor.getXMLParserClassName;

public class Main {
   public static void main( final String[] args ) throws Exception {
     // Gain direct access to Batik graphics context.
     final var userAgent = new UserAgentAdapter();
     final var loader = new DocumentLoader( userAgent );
     final var context = new BridgeContext( userAgent, loader );
     context.setDynamic( false );

     // Read the SVG file to render as PDF.
     final var factory = new SAXSVGDocumentFactory( getXMLParserClassName()
);
     final var svg = factory.createSVGDocument( "/tmp/poster.svg" );
     final var node = new GVTBuilder().build( context, svg );

     // Ensure that small bounds are enlarged.
     final var bounds = node.getPrimitiveBounds();
     final var w = (float) bounds.getWidth();
     final var h = (float) bounds.getHeight();
     final var scale = (w < 1 || h < 1) ? 100 : 1;

     // Create the PDF document model.
     final var pageSize = new PDRectangle( w * scale, h * scale );
     final var page = new PDPage( pageSize );
     final var document = new PDDocument();
     document.addPage( page );

     // Ask Batik to render upon the PDF's graphics context.
     final var graphics = new PdfBoxGraphics2D( document, w, h );
     node.setRenderingHints( RENDERING_HINTS );
     node.paint( graphics );
     graphics.dispose();

     // Instruct PDFBox to apply the drawn nodes.
     try( var writer = new PDPageContentStream( document, page ) ) {
       final var xform = graphics.getXFormObject();
       xform.setMatrix( getScaleInstance( scale, scale ) );
       writer.drawForm( xform );
     }

     // Export the PDFBox document to a file.
     final var pdfFile = new File( "/tmp/pdfbox-poster.pdf" );
     final var fos = newOutputStream(
       pdfFile.toPath(), WRITE, CREATE, TRUNCATE_EXISTING );
     document.save( fos );
     document.close();
     fos.close();

     System.out.println( "Created: " + pdfFile );
   }

   private static final Map<Object, Object> RENDERING_HINTS = Map.of(
     KEY_ANTIALIASING, VALUE_ANTIALIAS_ON,
     KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_QUALITY,
     KEY_COLOR_RENDERING, VALUE_COLOR_RENDER_QUALITY,
     KEY_DITHERING, VALUE_DITHER_DISABLE,
     KEY_FRACTIONALMETRICS, VALUE_FRACTIONALMETRICS_ON,
     KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC,
     KEY_RENDERING, VALUE_RENDER_QUALITY,
     KEY_STROKE_CONTROL, VALUE_STROKE_PURE,
     KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON
   );
}
// EOF

I can provide the graphics off-list, if needed.

Thank you!



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to